40307964a605ef75d366450e7406347334596374
[platform/upstream/libsolv.git] / bindings / solv.i
1 /*
2  * WARNING: for perl iterator/array support you need to run
3  *   sed -i -e 's/SvTYPE(tsv) == SVt_PVHV/SvTYPE(tsv) == SVt_PVHV || SvTYPE(tsv) == SVt_PVAV/'
4  * on the generated c code
5  */
6
7 %module solv
8
9 #ifdef SWIGRUBY
10 %markfunc Pool "mark_Pool";
11 #endif
12
13 /*
14  * binaryblob handling
15  */
16
17 %{
18 typedef struct {
19   const void *data;
20   size_t len;
21 } BinaryBlob;
22 %}
23
24 %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) {
25   res = SWIG_AsCharPtrAndSize($input, &buf, &size, &alloc);
26   if (!SWIG_IsOK(res)) {
27 #if defined(SWIGPYTHON)
28     const void *pybuf = 0;
29     Py_ssize_t pysize = 0;
30     res = PyObject_AsReadBuffer($input, &pybuf, &pysize);
31     if (res < 0) {
32       %argument_fail(res, "BinaryBlob", $symname, $argnum);
33     } else {
34       buf = (void *)pybuf;
35       size = pysize;
36     }
37 #else
38     %argument_fail(res, "const char *", $symname, $argnum);
39 #endif
40   }
41   $1 = (unsigned char *)buf;
42   $2 = size;
43 }
44
45 %typemap(freearg,noblock=1,match="in") (const unsigned char *str, int len) {
46   if (alloc$argnum == SWIG_NEWOBJ) %delete_array(buf$argnum);
47 }
48
49 %typemap(out,noblock=1,fragment="SWIG_FromCharPtrAndSize") BinaryBlob {
50 #if defined(SWIGPYTHON) && defined(PYTHON3)
51   $result = $1.data ? Py_BuildValue("y#", $1.data, $1.len) : SWIG_Py_Void();
52 #else
53   $result = SWIG_FromCharPtrAndSize($1.data, $1.len);
54 #if defined(SWIGPERL)
55   argvi++;
56 #endif
57 #endif
58 }
59
60 #if defined(SWIGPYTHON)
61 %typemap(in) Queue {
62   /* Check if is a list */
63   queue_init(&$1);
64   if (PyList_Check($input)) {
65     int size = PyList_Size($input);
66     int i = 0;
67     for (i = 0; i < size; i++) {
68       PyObject *o = PyList_GetItem($input,i);
69       int v;
70       int e = SWIG_AsVal_int(o, &v);
71       if (!SWIG_IsOK(e)) {
72         SWIG_exception_fail(SWIG_ArgError(e), "list must contain only integers");
73         queue_free(&$1);
74         return NULL;
75       }
76       queue_push(&$1, v);
77     }
78   } else {
79     PyErr_SetString(PyExc_TypeError,"not a list");
80     return NULL;
81   }
82 }
83
84 %typemap(out) Queue {
85   int i;
86   PyObject *o = PyList_New($1.count);
87   for (i = 0; i < $1.count; i++)
88     PyList_SetItem(o, i, SWIG_From_int($1.elements[i]));
89   queue_free(&$1);
90   $result = o;
91 }
92
93 %define Queue2Array(type, step, con) %{
94   int i;
95   int cnt = $1.count / step;
96   Id *idp = $1.elements;
97   PyObject *o = PyList_New(cnt);
98   for (i = 0; i < cnt; i++, idp += step)
99     {
100       Id id = *idp;
101 #define result resultx
102       type result = con;
103       $typemap(out, type)
104       PyList_SetItem(o, i, $result);
105 #undef result
106     }
107   queue_free(&$1);
108   $result = o;
109 %}
110
111 %enddef
112
113 #endif
114
115 #if defined(SWIGPERL)
116 %typemap(in) Queue {
117   AV *av;
118   int i, size;
119   queue_init(&$1);
120   if (!SvROK($input) || SvTYPE(SvRV($input)) != SVt_PVAV)
121     SWIG_croak("Argument $argnum is not an array reference.");
122   av = (AV*)SvRV($input);
123   size = av_len(av);
124   for (i = 0; i <= size; i++) {
125     SV **sv = av_fetch(av, i, 0);
126     int v;
127     int e = SWIG_AsVal_int(*sv, &v);
128     if (!SWIG_IsOK(e)) {
129       SWIG_croak("list must contain only integers");
130     }
131     queue_push(&$1, v);
132   }
133 }
134 /* AV *o = newAV();
135  * av_push(o, SvREFCNT_inc(SWIG_From_int($1.elements[i])));
136  * $result = newRV_noinc((SV*)o); argvi++;
137  */
138 %typemap(out) Queue {
139   int i;
140   if (argvi + $1.count + 1 >= items) {
141     EXTEND(sp, (argvi + $1.count + 1) - items + 1);
142   }
143   for (i = 0; i < $1.count; i++)
144     ST(argvi++) = SvREFCNT_inc(SWIG_From_int($1.elements[i]));
145   queue_free(&$1);
146   $result = 0;
147 }
148 %define Queue2Array(type, step, con) %{
149   int i;
150   int cnt = $1.count / step;
151   Id *idp = $1.elements;
152   if (argvi + cnt + 1 >= items) {
153     EXTEND(sp, (argvi + cnt + 1) - items + 1);
154   }
155   for (i = 0; i < cnt; i++, idp += step)
156     {
157       Id id = *idp;
158 #define result resultx
159       type result = con;
160       $typemap(out, type)
161       SvREFCNT_inc(ST(argvi - 1));
162 #undef result
163     }
164   queue_free(&$1);
165   $result = 0;
166 %}
167 %enddef
168
169 #endif
170
171 %typemap(arginit) Queue {
172   queue_init(&$1);
173 }
174 %typemap(freearg) Queue {
175   queue_free(&$1);
176 }
177
178 #if defined(SWIGRUBY)
179 %typemap(in) Queue {
180   int size, i;
181   VALUE *o;
182   queue_init(&$1);
183   size = RARRAY_LEN($input);
184   i = 0;
185   o = RARRAY_PTR($input);
186   for (i = 0; i < size; i++, o++) {
187     int v;
188     int e = SWIG_AsVal_int(*o, &v);
189     if (!SWIG_IsOK(e))
190       {
191         SWIG_Error(SWIG_RuntimeError, "list must contain only integers");
192         SWIG_fail;
193       }
194     queue_push(&$1, v);
195   }
196 }
197 %typemap(out) Queue {
198   int i;
199   VALUE o = rb_ary_new2($1.count);
200   for (i = 0; i < $1.count; i++)
201     rb_ary_store(o, i, SWIG_From_int($1.elements[i]));
202   queue_free(&$1);
203   $result = o;
204 }
205 %typemap(arginit) Queue {
206   queue_init(&$1);
207 }
208 %typemap(freearg) Queue {
209   queue_free(&$1);
210 }
211 %define Queue2Array(type, step, con) %{
212   int i;
213   int cnt = $1.count / step;
214   Id *idp = $1.elements;
215   VALUE o = rb_ary_new2(cnt);
216   for (i = 0; i < cnt; i++, idp += step)
217     {
218       Id id = *idp;
219 #define result resultx
220       type result = con;
221       $typemap(out, type)
222       rb_ary_store(o, i, $result);
223 #undef result
224     }
225   queue_free(&$1);
226   $result = o;
227 %}
228 %enddef
229 #endif
230
231
232
233
234 #if defined(SWIGPERL)
235
236 /* work around a swig bug */
237 %{
238 #undef SWIG_CALLXS
239 #ifdef PERL_OBJECT
240 #  define SWIG_CALLXS(_name) TOPMARK=MARK-PL_stack_base;_name(cv,pPerl)
241 #else
242 #  ifndef MULTIPLICITY
243 #    define SWIG_CALLXS(_name) TOPMARK=MARK-PL_stack_base;_name(cv)
244 #  else
245 #    define SWIG_CALLXS(_name) TOPMARK=MARK-PL_stack_base;_name(PERL_GET_THX, cv)
246 #  endif
247 #endif
248 %}
249
250
251 %define perliter(class)
252   %perlcode {
253     sub class##::FETCH {
254       my $i = ${##class##::ITERATORS}{$_[0]};
255       if ($i) {
256         $_[1] == $i->[0] - 1 ? $i->[1] : undef;
257       } else {
258         $_[0]->__getitem__($_[1]);
259       }
260     }
261     sub class##::FETCHSIZE {
262       my $i = ${##class##::ITERATORS}{$_[0]};
263       if ($i) {
264         ($i->[1] = $_[0]->__next__()) ? ++$i->[0]  : 0;
265       } else {
266         $_[0]->__len__();
267       }
268     }
269   }
270 %enddef
271
272 %{
273
274 #define SWIG_PERL_ITERATOR      0x80
275
276 SWIGRUNTIMEINLINE SV *
277 SWIG_Perl_NewArrayObj(SWIG_MAYBE_PERL_OBJECT void *ptr, swig_type_info *t, int flags) {
278   SV *result = sv_newmortal();
279   if (ptr && (flags & (SWIG_SHADOW | SWIG_POINTER_OWN))) {
280     SV *self;
281     SV *obj=newSV(0);
282     AV *array=newAV();
283     HV *stash;
284     sv_setref_pv(obj, (char *) SWIG_Perl_TypeProxyName(t), ptr);
285     stash=SvSTASH(SvRV(obj));
286     if (flags & SWIG_POINTER_OWN) {
287       HV *hv;
288       GV *gv=*(GV**)hv_fetch(stash, "OWNER", 5, TRUE);
289       if (!isGV(gv))
290         gv_init(gv, stash, "OWNER", 5, FALSE);
291       hv=GvHVn(gv);
292       hv_store_ent(hv, obj, newSViv(1), 0);
293     }
294     if (flags & SWIG_PERL_ITERATOR) {
295       HV *hv;
296       GV *gv=*(GV**)hv_fetch(stash, "ITERATORS", 9, TRUE);
297       AV *av=newAV();
298       if (!isGV(gv))
299         gv_init(gv, stash, "ITERATORS", 9, FALSE);
300       hv=GvHVn(gv);
301       hv_store_ent(hv, obj, newRV_inc((SV *)av), 0);
302     }
303     sv_magic((SV *)array, (SV *)obj, 'P', Nullch, 0);
304     SvREFCNT_dec(obj);
305     self=newRV_noinc((SV *)array);
306     sv_setsv(result, self);
307     SvREFCNT_dec((SV *)self);
308     sv_bless(result, stash);
309   } else {
310     sv_setref_pv(result, (char *) SWIG_Perl_TypeProxyName(t), ptr);
311   }
312   return result;
313 }
314
315 %}
316
317 %typemap(out) Perlarray {
318   ST(argvi) = SWIG_Perl_NewArrayObj(SWIG_PERL_OBJECT_CALL SWIG_as_voidptr(result), $1_descriptor, $owner | $shadow); argvi++;
319 }
320 %typemap(out) Perliterator {
321   ST(argvi) = SWIG_Perl_NewArrayObj(SWIG_PERL_OBJECT_CALL SWIG_as_voidptr(result), $1_descriptor, $owner | $shadow | SWIG_PERL_ITERATOR); argvi++;
322 }
323
324 %typemap(out) Pool_solvable_iterator * = Perlarray;
325 %typemap(out) Pool_solvable_iterator * solvables_iter = Perliterator;
326 %typemap(out) Pool_repo_iterator * = Perlarray;
327 %typemap(out) Pool_repo_iterator * repos_iter = Perliterator;
328 %typemap(out) Repo_solvable_iterator * = Perlarray;
329 %typemap(out) Repo_solvable_iterator * solvables_iter = Perliterator;
330 %typemap(out) Dataiterator * = Perliterator;
331
332 #endif
333
334
335 #if defined(SWIGPYTHON)
336 typedef PyObject *AppObjectPtr;
337 %typemap(out) AppObjectPtr {
338   $result = $1 ? $1 : Py_None;
339   Py_INCREF($result);
340 }
341 #endif
342 #if defined(SWIGPERL)
343 typedef SV *AppObjectPtr;
344 %typemap(in) AppObjectPtr {
345   $1 = SvROK($input) ? SvRV($input) : 0;
346 }
347 %typemap(out) AppObjectPtr {
348   $result = $1 ? newRV_inc($1) : newSV(0);
349   argvi++;
350 }
351 #endif
352 #if defined(SWIGRUBY)
353 typedef VALUE AppObjectPtr;
354 %typemap(in) AppObjectPtr {
355   $1 = (void *)$input;
356 }
357 %typemap(out) AppObjectPtr {
358   $result = (VALUE)$1;
359 }
360 #endif
361
362
363 #ifdef SWIGPYTHON
364 %include "file.i"
365 #else
366 %fragment("SWIG_AsValFilePtr","header") {}
367 #endif
368
369
370 %fragment("SWIG_AsValSolvFpPtr","header", fragment="SWIG_AsValFilePtr") {
371
372 SWIGINTERN int
373 #ifdef SWIGRUBY
374 SWIG_AsValSolvFpPtr(VALUE obj, FILE **val) {
375 #else
376 SWIG_AsValSolvFpPtr(void *obj, FILE **val) {
377 #endif
378   static swig_type_info* desc = 0;
379   void *vptr = 0;
380   int ecode;
381
382   if (!desc) desc = SWIG_TypeQuery("SolvFp *");
383   if ((SWIG_ConvertPtr(obj, &vptr, desc, 0)) == SWIG_OK) {
384     if (val)
385       *val = vptr ? ((SolvFp *)vptr)->fp : 0;
386     return SWIG_OK;
387   }
388 #ifdef SWIGPYTHON
389   ecode = SWIG_AsValFilePtr(obj, val);
390   if (ecode == SWIG_OK)
391     return ecode;
392 #endif
393   return SWIG_TypeError;
394 }
395
396 }
397
398
399 %fragment("SWIG_AsValDepId","header") {
400
401 SWIGINTERN int
402 #ifdef SWIGRUBY
403 SWIG_AsValDepId(VALUE obj, int *val) {
404 #else
405 SWIG_AsValDepId(void *obj, int *val) {
406 #endif
407   static swig_type_info* desc = 0;
408   void *vptr = 0;
409   int ecode;
410   if (!desc) desc = SWIG_TypeQuery("Dep *");
411   ecode = SWIG_AsVal_int(obj, val);
412   if (SWIG_IsOK(ecode))
413     return ecode;
414   if ((SWIG_ConvertPtr(obj, &vptr, desc, 0)) == SWIG_OK) {
415     if (val)
416       *val = vptr ? ((Dep *)vptr)->id : 0;
417     return SWIG_OK;
418   }
419   return SWIG_TypeError;
420 }
421
422 }
423
424 %typemap(out) disown_helper {
425 #ifdef SWIGRUBY
426   SWIG_ConvertPtr(self, &argp1,SWIGTYPE_p_Pool, SWIG_POINTER_DISOWN |  0 );
427 #endif
428 #ifdef SWIGPYTHON
429   SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_Pool, SWIG_POINTER_DISOWN |  0 );
430 #endif
431 #ifdef SWIGPERL
432   SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_Pool, SWIG_POINTER_DISOWN |  0 );
433 #endif
434   $result = SWIG_From_int((int)(0));
435 }
436
437 %include "typemaps.i"
438
439 %typemap(in,numinputs=0,noblock=1) XRule **OUTPUT ($*1_ltype temp) {
440   $1 = &temp;
441 }
442 %typemap(argout,noblock=1) XRule **OUTPUT {
443   %append_output(SWIG_NewPointerObj((void*)(*$1), SWIGTYPE_p_XRule, SWIG_POINTER_OWN | %newpointer_flags));
444 }
445
446 %typemaps_asval(%checkcode(POINTER), SWIG_AsValSolvFpPtr, "SWIG_AsValSolvFpPtr", FILE*);
447 %typemaps_asval(%checkcode(INT32), SWIG_AsValDepId, "SWIG_AsValDepId", DepId);
448
449
450 %{
451 #include <stdbool.h>
452 #include <stdio.h>
453 #include <sys/stat.h>
454 #include <sys/utsname.h>
455 #include <sys/types.h>
456 #include <unistd.h>
457
458 /* argh, swig undefs bool for perl */
459 #ifndef bool
460 typedef int bool;
461 #endif
462
463 #include "pool.h"
464 #include "poolarch.h"
465 #include "evr.h"
466 #include "solver.h"
467 #include "policy.h"
468 #include "solverdebug.h"
469 #include "repo_solv.h"
470 #include "chksum.h"
471 #include "selection.h"
472
473 #include "repo_write.h"
474 #ifdef ENABLE_RPMDB
475 #include "repo_rpmdb.h"
476 #endif
477 #ifdef ENABLE_PUBKEY
478 #include "repo_pubkey.h"
479 #endif
480 #ifdef ENABLE_DEBIAN
481 #include "repo_deb.h"
482 #endif
483 #ifdef ENABLE_RPMMD
484 #include "repo_rpmmd.h"
485 #include "repo_updateinfoxml.h"
486 #include "repo_deltainfoxml.h"
487 #include "repo_repomdxml.h"
488 #endif
489 #ifdef ENABLE_SUSEREPO
490 #include "repo_products.h"
491 #include "repo_susetags.h"
492 #include "repo_content.h"
493 #endif
494 #ifdef ENABLE_MDKREPO
495 #include "repo_mdk.h"
496 #endif
497 #ifdef ENABLE_ARCHREPO
498 #include "repo_arch.h"
499 #endif
500 #ifdef SUSE
501 #include "repo_autopattern.h"
502 #endif
503 #include "solv_xfopen.h"
504
505 /* for old ruby versions */
506 #ifndef RARRAY_PTR
507 #define RARRAY_PTR(ary) (RARRAY(ary)->ptr)
508 #endif
509 #ifndef RARRAY_LEN
510 #define RARRAY_LEN(ary) (RARRAY(ary)->len)
511 #endif
512
513 #define SOLVER_SOLUTION_ERASE                   -100
514 #define SOLVER_SOLUTION_REPLACE                 -101
515 #define SOLVER_SOLUTION_REPLACE_DOWNGRADE       -102
516 #define SOLVER_SOLUTION_REPLACE_ARCHCHANGE      -103
517 #define SOLVER_SOLUTION_REPLACE_VENDORCHANGE    -104
518 #define SOLVER_SOLUTION_REPLACE_NAMECHANGE      -105
519
520 typedef void *AppObjectPtr;
521 typedef Id DepId;
522
523 typedef struct {
524   Pool *pool;
525   Id id;
526 } Dep;
527
528 typedef struct {
529   Pool *pool;
530   Id id;
531 } XSolvable;
532
533 typedef struct {
534   Solver *solv;
535   Id id;
536 } XRule;
537
538 typedef struct {
539   Repo *repo;
540   Id id;
541 } XRepodata;
542
543 typedef struct {
544   Pool *pool;
545   Id id;
546 } Pool_solvable_iterator;
547
548 typedef struct {
549   Pool *pool;
550   Id id;
551 } Pool_repo_iterator;
552
553 typedef struct {
554   Repo *repo;
555   Id id;
556 } Repo_solvable_iterator;
557
558 typedef struct {
559   Pool *pool;
560   int how;
561   Id what;
562 } Job;
563
564 typedef struct {
565   Solver *solv;
566   Id id;
567 } Problem;
568
569 typedef struct {
570   Solver *solv;
571   Id problemid;
572   Id id;
573 } Solution;
574
575 typedef struct {
576   Solver *solv;
577   Id problemid;
578   Id solutionid;
579   Id id;
580
581   Id type;
582   Id p;
583   Id rp;
584 } Solutionelement;
585
586 typedef struct {
587   Solver *solv;
588   Id rid;
589   Id type;
590   Id source;
591   Id target;
592   Id dep_id;
593 } Ruleinfo;
594
595 typedef struct {
596   Solver *solv;
597   Id type;
598   Id rid;
599   Id from_id;
600   Id dep_id;
601   Id chosen_id;
602   Queue choices;
603   int level;
604 } Alternative;
605
606 typedef struct {
607   Transaction *transaction;
608   int mode;
609   Id type;
610   int count;
611   Id fromid;
612   Id toid;
613 } TransactionClass;
614
615 typedef struct {
616   Pool *pool;
617   Queue q;
618   int flags;
619 } Selection;
620
621 typedef struct {
622   FILE *fp;
623 } SolvFp;
624
625 typedef Dataiterator Datamatch;
626
627 typedef int disown_helper;
628
629 %}
630
631 #ifdef SWIGRUBY
632 %mixin Dataiterator "Enumerable";
633 %mixin Pool_solvable_iterator "Enumerable";
634 %mixin Pool_repo_iterator "Enumerable";
635 %mixin Repo_solvable_iterator "Enumerable";
636 #endif
637
638 typedef int Id;
639
640 %include "knownid.h"
641
642 /* from repodata.h */
643 %constant Id SOLVID_META;
644 %constant Id SOLVID_POS;
645
646 %constant int REL_EQ;
647 %constant int REL_GT;
648 %constant int REL_LT;
649 %constant int REL_ARCH;
650
651 typedef struct {
652   Pool* const pool;
653 } Selection;
654
655 typedef struct {
656   Pool* const pool;
657   Id const id;
658 } Dep;
659
660 /* put before pool/repo so we can access the constructor */
661 %nodefaultdtor Dataiterator;
662 typedef struct {} Dataiterator;
663
664 typedef struct {
665   Pool* const pool;
666   Id const id;
667 } XSolvable;
668
669 typedef struct {
670   Solver* const solv;
671   Id const type;
672   Id const dep_id;
673 } Ruleinfo;
674
675 typedef struct {
676   Solver* const solv;
677   Id const id;
678 } XRule;
679
680 typedef struct {
681   Repo* const repo;
682   Id const id;
683 } XRepodata;
684
685 typedef struct {} Pool_solvable_iterator;
686 typedef struct {} Pool_repo_iterator;
687 typedef struct {} Repo_solvable_iterator;
688
689 %nodefaultctor Datamatch;
690 %nodefaultdtor Datamatch;
691 typedef struct {
692   Pool * const pool;
693   Repo * const repo;
694   Id const solvid;
695 } Datamatch;
696
697 %nodefaultctor Datapos;
698 typedef struct {
699   Repo * const repo;
700 } Datapos;
701
702 typedef struct {
703   Pool * const pool;
704   int how;
705   Id what;
706 } Job;
707
708 %nodefaultctor Pool;
709 %nodefaultdtor Pool;
710 typedef struct {
711   AppObjectPtr appdata;
712 } Pool;
713
714 %nodefaultctor Repo;
715 %nodefaultdtor Repo;
716 typedef struct {
717   Pool * const pool;
718   const char * const name;
719   int priority;
720   int subpriority;
721   int const nsolvables;
722   AppObjectPtr appdata;
723 } Repo;
724
725 %nodefaultctor Solver;
726 %nodefaultdtor Solver;
727 typedef struct {
728   Pool * const pool;
729 } Solver;
730
731 typedef struct {
732 } Chksum;
733
734 #ifdef ENABLE_PUBKEY
735 typedef struct {
736   Id const htype;
737   unsigned int const created;
738   unsigned int const expires;
739   const char * const keyid;
740 } Solvsig;
741 #endif
742
743 %rename(xfopen) solvfp_xfopen;
744 %rename(xfopen_fd) solvfp_xfopen_fd;
745
746 %nodefaultctor SolvFp;
747 typedef struct {
748 } SolvFp;
749
750 %newobject solvfp_xfopen;
751 %newobject solvfp_xfopen_fd;
752
753 SolvFp *solvfp_xfopen(const char *fn, const char *mode = 0);
754 SolvFp *solvfp_xfopen_fd(const char *fn, int fd, const char *mode = 0);
755
756 %{
757   SWIGINTERN SolvFp *solvfp_xfopen_fd(const char *fn, int fd, const char *mode) {
758     SolvFp *sfp;
759     FILE *fp;
760     fd = dup(fd);
761     fp = fd == -1 ? 0 : solv_xfopen_fd(fn, fd, mode);
762     if (!fp)
763       return 0;
764     sfp = solv_calloc(1, sizeof(SolvFp));
765     sfp->fp = fp;
766     return sfp;
767   }
768   SWIGINTERN SolvFp *solvfp_xfopen(const char *fn, const char *mode) {
769     SolvFp *sfp;
770     FILE *fp;
771     fp = solv_xfopen(fn, mode);
772     if (!fp)
773       return 0;
774     sfp = solv_calloc(1, sizeof(SolvFp));
775     sfp->fp = fp;
776     return sfp;
777   }
778 %}
779
780 typedef struct {
781   Solver * const solv;
782   Id const id;
783 } Problem;
784
785 typedef struct {
786   Solver * const solv;
787   Id const problemid;
788   Id const id;
789 } Solution;
790
791 typedef struct {
792   Solver *const solv;
793   Id const problemid;
794   Id const solutionid;
795   Id const id;
796   Id const type;
797 } Solutionelement;
798
799 %nodefaultctor Alternative;
800 typedef struct {
801   Solver *const solv;
802   Id const type;
803   Id const rid;
804   Id const from_id;
805   Id const dep_id;
806   Id const chosen_id;
807   int level;
808 } Alternative;
809
810 %nodefaultctor Transaction;
811 %nodefaultdtor Transaction;
812 typedef struct {
813   Pool * const pool;
814 } Transaction;
815
816 typedef struct {
817   Transaction * const transaction;
818   Id const type;
819   Id const fromid;
820   Id const toid;
821   int const count;
822 } TransactionClass;
823
824 %extend SolvFp {
825   ~SolvFp() {
826     if ($self->fp)
827       fclose($self->fp);
828     free($self);
829   }
830   int fileno() {
831     return $self->fp ? fileno($self->fp) : -1;
832   }
833   int dup() {
834     return $self->fp ? dup(fileno($self->fp)) : -1;
835   }
836   bool flush() {
837     if (!$self->fp)
838       return 1;
839     return fflush($self->fp) == 0;
840   }
841   bool close() {
842     bool ret;
843     if (!$self->fp)
844       return 1;
845     ret = fclose($self->fp) == 0;
846     $self->fp = 0;
847     return ret;
848   }
849 }
850
851 %extend Job {
852   static const Id SOLVER_SOLVABLE = SOLVER_SOLVABLE;
853   static const Id SOLVER_SOLVABLE_NAME = SOLVER_SOLVABLE_NAME;
854   static const Id SOLVER_SOLVABLE_PROVIDES = SOLVER_SOLVABLE_PROVIDES;
855   static const Id SOLVER_SOLVABLE_ONE_OF = SOLVER_SOLVABLE_ONE_OF;
856   static const Id SOLVER_SOLVABLE_REPO = SOLVER_SOLVABLE_REPO;
857   static const Id SOLVER_SOLVABLE_ALL = SOLVER_SOLVABLE_ALL;
858   static const Id SOLVER_SELECTMASK = SOLVER_SELECTMASK;
859   static const Id SOLVER_NOOP = SOLVER_NOOP;
860   static const Id SOLVER_INSTALL = SOLVER_INSTALL;
861   static const Id SOLVER_ERASE = SOLVER_ERASE;
862   static const Id SOLVER_UPDATE = SOLVER_UPDATE;
863   static const Id SOLVER_WEAKENDEPS = SOLVER_WEAKENDEPS;
864   static const Id SOLVER_MULTIVERSION = SOLVER_MULTIVERSION;
865   static const Id SOLVER_LOCK = SOLVER_LOCK;
866   static const Id SOLVER_DISTUPGRADE = SOLVER_DISTUPGRADE;
867   static const Id SOLVER_VERIFY = SOLVER_VERIFY;
868   static const Id SOLVER_DROP_ORPHANED = SOLVER_DROP_ORPHANED;
869   static const Id SOLVER_USERINSTALLED = SOLVER_USERINSTALLED;
870   static const Id SOLVER_JOBMASK = SOLVER_JOBMASK;
871   static const Id SOLVER_WEAK = SOLVER_WEAK;
872   static const Id SOLVER_ESSENTIAL = SOLVER_ESSENTIAL;
873   static const Id SOLVER_CLEANDEPS = SOLVER_CLEANDEPS;
874   static const Id SOLVER_FORCEBEST = SOLVER_FORCEBEST;
875   static const Id SOLVER_TARGETED = SOLVER_TARGETED;
876   static const Id SOLVER_NOTBYUSER = SOLVER_NOTBYUSER;
877   static const Id SOLVER_SETEV = SOLVER_SETEV;
878   static const Id SOLVER_SETEVR = SOLVER_SETEVR;
879   static const Id SOLVER_SETARCH = SOLVER_SETARCH;
880   static const Id SOLVER_SETVENDOR = SOLVER_SETVENDOR;
881   static const Id SOLVER_SETREPO = SOLVER_SETREPO;
882   static const Id SOLVER_SETNAME = SOLVER_SETNAME;
883   static const Id SOLVER_NOAUTOSET = SOLVER_NOAUTOSET;
884   static const Id SOLVER_SETMASK = SOLVER_SETMASK;
885
886   Job(Pool *pool, int how, Id what) {
887     Job *job = solv_calloc(1, sizeof(*job));
888     job->pool = pool;
889     job->how = how;
890     job->what = what;
891     return job;
892   }
893
894   %typemap(out) Queue solvables Queue2Array(XSolvable *, 1, new_XSolvable(arg1->pool, id));
895   %newobject solvables;
896   Queue solvables() {
897     Queue q;
898     queue_init(&q);
899     pool_job2solvables($self->pool, &q, $self->how, $self->what);
900     return q;
901   }
902 #ifdef SWIGRUBY
903   %rename("isemptyupdate?") isemptyupdate;
904 #endif
905   bool isemptyupdate() {
906     return pool_isemptyupdatejob($self->pool, $self->how, $self->what);
907   }
908
909   bool __eq__(Job *j) {
910     return $self->pool == j->pool && $self->how == j->how && $self->what == j->what;
911   }
912   bool __ne__(Job *j) {
913     return !Job___eq__($self, j);
914   }
915 #if defined(SWIGPERL)
916   %rename("str") __str__;
917 #endif
918   const char *__str__() {
919     return pool_job2str($self->pool, $self->how, $self->what, 0);
920   }
921   const char *__repr__() {
922     const char *str = pool_job2str($self->pool, $self->how, $self->what, ~0);
923     return pool_tmpjoin($self->pool, "<Job ", str, ">");
924   }
925 }
926
927 %extend Selection {
928   static const Id SELECTION_NAME = SELECTION_NAME;
929   static const Id SELECTION_PROVIDES = SELECTION_PROVIDES;
930   static const Id SELECTION_FILELIST = SELECTION_FILELIST;
931   static const Id SELECTION_CANON = SELECTION_CANON;
932   static const Id SELECTION_DOTARCH = SELECTION_DOTARCH;
933   static const Id SELECTION_REL = SELECTION_REL;
934   static const Id SELECTION_INSTALLED_ONLY = SELECTION_INSTALLED_ONLY;
935   static const Id SELECTION_GLOB = SELECTION_GLOB;
936   static const Id SELECTION_FLAT = SELECTION_FLAT;
937   static const Id SELECTION_NOCASE = SELECTION_NOCASE;
938   static const Id SELECTION_SOURCE_ONLY = SELECTION_SOURCE_ONLY;
939   static const Id SELECTION_WITH_SOURCE = SELECTION_WITH_SOURCE;
940
941   Selection(Pool *pool) {
942     Selection *s;
943     s = solv_calloc(1, sizeof(*s));
944     s->pool = pool;
945     return s;
946   }
947
948   ~Selection() {
949     queue_free(&$self->q);
950     solv_free($self);
951   }
952   int flags() {
953     return $self->flags;
954   }
955 #ifdef SWIGRUBY
956   %rename("isempty?") isempty;
957 #endif
958   bool isempty() {
959     return $self->q.count == 0;
960   }
961   void filter(Selection *lsel) {
962     if ($self->pool != lsel->pool)
963       queue_empty(&$self->q);
964     else
965       selection_filter($self->pool, &$self->q, &lsel->q);
966   }
967   void add(Selection *lsel) {
968     if ($self->pool == lsel->pool)
969       {
970         selection_add($self->pool, &$self->q, &lsel->q);
971         $self->flags |= lsel->flags;
972       }
973   }
974   void add_raw(Id how, Id what) {
975     queue_push2(&$self->q, how, what);
976   }
977   %typemap(out) Queue jobs Queue2Array(Job *, 2, new_Job(arg1->pool, id, idp[1]));
978   %newobject jobs;
979   Queue jobs(int flags) {
980     Queue q;
981     int i;
982     queue_init_clone(&q, &$self->q);
983     for (i = 0; i < q.count; i += 2)
984       q.elements[i] |= flags;
985     return q;
986   }
987
988   %typemap(out) Queue solvables Queue2Array(XSolvable *, 1, new_XSolvable(arg1->pool, id));
989   %newobject solvables;
990   Queue solvables() {
991     Queue q;
992     queue_init(&q);
993     selection_solvables($self->pool, &$self->q, &q);
994     return q;
995   }
996
997 #if defined(SWIGPERL)
998   %rename("str") __str__;
999 #endif
1000   const char *__str__() {
1001     return pool_selection2str($self->pool, &$self->q, 0);
1002   }
1003   const char *__repr__() {
1004     const char *str = pool_selection2str($self->pool, &$self->q, ~0);
1005     return pool_tmpjoin($self->pool, "<Selection ", str, ">");
1006   }
1007 }
1008
1009 %extend Chksum {
1010   Chksum(Id type) {
1011     return solv_chksum_create(type);
1012   }
1013   Chksum(Id type, const char *hex) {
1014     unsigned char buf[64];
1015     int l = solv_chksum_len(type);
1016     if (!l)
1017       return 0;
1018     if (solv_hex2bin(&hex, buf, sizeof(buf)) != l || hex[0])
1019       return 0;
1020     return solv_chksum_create_from_bin(type, buf);
1021   }
1022   ~Chksum() {
1023     solv_chksum_free($self, 0);
1024   }
1025   Id const type;
1026   %{
1027   SWIGINTERN Id Chksum_type_get(Chksum *chk) {
1028     return solv_chksum_get_type(chk);
1029   }
1030   %}
1031   void add(const unsigned char *str, size_t len) {
1032     solv_chksum_add($self, str, (int)len);
1033   }
1034   void add_fp(FILE *fp) {
1035     char buf[4096];
1036     int l;
1037     while ((l = fread(buf, 1, sizeof(buf), fp)) > 0)
1038       solv_chksum_add($self, buf, l);
1039     rewind(fp);         /* convenience */
1040   }
1041   void add_fd(int fd) {
1042     char buf[4096];
1043     int l;
1044     while ((l = read(fd, buf, sizeof(buf))) > 0)
1045       solv_chksum_add($self, buf, l);
1046     lseek(fd, 0, 0);    /* convenience */
1047   }
1048   void add_stat(const char *filename) {
1049     struct stat stb;
1050     if (stat(filename, &stb))
1051       memset(&stb, 0, sizeof(stb));
1052     solv_chksum_add($self, &stb.st_dev, sizeof(stb.st_dev));
1053     solv_chksum_add($self, &stb.st_ino, sizeof(stb.st_ino));
1054     solv_chksum_add($self, &stb.st_size, sizeof(stb.st_size));
1055     solv_chksum_add($self, &stb.st_mtime, sizeof(stb.st_mtime));
1056   }
1057   void add_fstat(int fd) {
1058     struct stat stb;
1059     if (fstat(fd, &stb))
1060       memset(&stb, 0, sizeof(stb));
1061     solv_chksum_add($self, &stb.st_dev, sizeof(stb.st_dev));
1062     solv_chksum_add($self, &stb.st_ino, sizeof(stb.st_ino));
1063     solv_chksum_add($self, &stb.st_size, sizeof(stb.st_size));
1064     solv_chksum_add($self, &stb.st_mtime, sizeof(stb.st_mtime));
1065   }
1066   BinaryBlob raw() {
1067     BinaryBlob bl;
1068     int l;
1069     const unsigned char *b;
1070     b = solv_chksum_get($self, &l);
1071     bl.data = b;
1072     bl.len = l;
1073     return bl;
1074   }
1075   %newobject hex;
1076   char *hex() {
1077     int l;
1078     const unsigned char *b;
1079     char *ret;
1080
1081     b = solv_chksum_get($self, &l);
1082     ret = solv_malloc(2 * l + 1);
1083     solv_bin2hex(b, l, ret);
1084     return ret;
1085   }
1086   const char *typestr() {
1087     return solv_chksum_type2str(solv_chksum_get_type($self));
1088   }
1089
1090   bool __eq__(Chksum *chk) {
1091     int l;
1092     const unsigned char *b, *bo;
1093     if (!chk)
1094       return 0;
1095     if (solv_chksum_get_type($self) != solv_chksum_get_type(chk))
1096       return 0;
1097     b = solv_chksum_get($self, &l);
1098     bo = solv_chksum_get(chk, 0);
1099     return memcmp(b, bo, l) == 0;
1100   }
1101   bool __ne__(Chksum *chk) {
1102     return !Chksum___eq__($self, chk);
1103   }
1104 #if defined(SWIGRUBY)
1105   %rename("to_s") __str__;
1106 #endif
1107 #if defined(SWIGPERL)
1108   %rename("str") __str__;
1109 #endif
1110   %newobject __str__;
1111   const char *__str__() {
1112     const char *str;
1113     const char *h = 0;
1114     if (solv_chksum_isfinished($self))
1115       h = Chksum_hex($self);
1116     str = solv_dupjoin(solv_chksum_type2str(solv_chksum_get_type($self)), ":", h ? h : "unfinished");
1117     solv_free((void *)h);
1118     return str;
1119   }
1120   %newobject __repr__;
1121   const char *__repr__() {
1122     const char *h = Chksum___str__($self);
1123     const char *str = solv_dupjoin("<Chksum ", h, ">");
1124     solv_free((void *)h);
1125     return str;
1126   }
1127 }
1128
1129 %extend Pool {
1130   static const int POOL_FLAG_PROMOTEEPOCH = POOL_FLAG_PROMOTEEPOCH;
1131   static const int POOL_FLAG_FORBIDSELFCONFLICTS = POOL_FLAG_FORBIDSELFCONFLICTS;
1132   static const int POOL_FLAG_OBSOLETEUSESPROVIDES = POOL_FLAG_OBSOLETEUSESPROVIDES;
1133   static const int POOL_FLAG_IMPLICITOBSOLETEUSESPROVIDES = POOL_FLAG_IMPLICITOBSOLETEUSESPROVIDES;
1134   static const int POOL_FLAG_OBSOLETEUSESCOLORS = POOL_FLAG_OBSOLETEUSESCOLORS;
1135   static const int POOL_FLAG_IMPLICITOBSOLETEUSESCOLORS = POOL_FLAG_IMPLICITOBSOLETEUSESCOLORS;
1136   static const int POOL_FLAG_NOINSTALLEDOBSOLETES = POOL_FLAG_NOINSTALLEDOBSOLETES;
1137   static const int POOL_FLAG_HAVEDISTEPOCH = POOL_FLAG_HAVEDISTEPOCH;
1138   static const int POOL_FLAG_NOOBSOLETESMULTIVERSION = POOL_FLAG_NOOBSOLETESMULTIVERSION;
1139
1140   Pool() {
1141     Pool *pool = pool_create();
1142     return pool;
1143   }
1144   void set_debuglevel(int level) {
1145     pool_setdebuglevel($self, level);
1146   }
1147   int set_flag(int flag, int value) {
1148     return pool_set_flag($self, flag, value);
1149   }
1150   int get_flag(int flag) {
1151     return pool_get_flag($self, flag);
1152   }
1153   void set_rootdir(const char *rootdir) {
1154     pool_set_rootdir($self, rootdir);
1155   }
1156   const char *get_rootdir(int flag) {
1157     return pool_get_rootdir($self);
1158   }
1159 #if defined(SWIGPYTHON)
1160   %{
1161   SWIGINTERN int loadcallback(Pool *pool, Repodata *data, void *d) {
1162     XRepodata *xd = new_XRepodata(data->repo, data->repodataid);
1163     PyObject *args = Py_BuildValue("(O)", SWIG_NewPointerObj(SWIG_as_voidptr(xd), SWIGTYPE_p_XRepodata, SWIG_POINTER_OWN | 0));
1164     PyObject *result = PyEval_CallObject((PyObject *)d, args);
1165     int ecode = 0;
1166     int vresult = 0;
1167     Py_DECREF(args);
1168     if (!result)
1169       return 0; /* exception */
1170     ecode = SWIG_AsVal_int(result, &vresult);
1171     Py_DECREF(result);
1172     return SWIG_IsOK(ecode) ? vresult : 0;
1173   }
1174   %}
1175   void set_loadcallback(PyObject *callable) {
1176     if ($self->loadcallback == loadcallback) {
1177       PyObject *obj = $self->loadcallbackdata;
1178       Py_DECREF(obj);
1179     }
1180     if (callable) {
1181       Py_INCREF(callable);
1182     }
1183     pool_setloadcallback($self, callable ? loadcallback : 0, callable);
1184   }
1185 #endif
1186 #if defined(SWIGPERL)
1187 %{
1188   SWIGINTERN int loadcallback(Pool *pool, Repodata *data, void *d) {
1189     int count;
1190     int ret = 0;
1191     dSP;
1192     XRepodata *xd = new_XRepodata(data->repo, data->repodataid);
1193
1194     ENTER;
1195     SAVETMPS;
1196     PUSHMARK(SP);
1197     XPUSHs(SWIG_NewPointerObj(SWIG_as_voidptr(xd), SWIGTYPE_p_XRepodata, SWIG_OWNER | SWIG_SHADOW));
1198     PUTBACK;
1199     count = perl_call_sv((SV *)d, G_EVAL|G_SCALAR);
1200     SPAGAIN;
1201     if (count)
1202       ret = POPi;
1203     PUTBACK;
1204     FREETMPS;
1205     LEAVE;
1206     return ret;
1207   }
1208 %}
1209   void set_loadcallback(SV *callable) {
1210     if ($self->loadcallback == loadcallback)
1211       SvREFCNT_dec($self->loadcallbackdata);
1212     if (callable)
1213       SvREFCNT_inc(callable);
1214     pool_setloadcallback($self, callable ? loadcallback : 0, callable);
1215   }
1216 #endif
1217
1218 #if defined(SWIGRUBY)
1219 %{
1220   SWIGINTERN int loadcallback(Pool *pool, Repodata *data, void *d) {
1221     XRepodata *xd = new_XRepodata(data->repo, data->repodataid);
1222     VALUE callable = (VALUE)d;
1223     VALUE rd = SWIG_NewPointerObj(SWIG_as_voidptr(xd), SWIGTYPE_p_XRepodata, SWIG_POINTER_OWN | 0);
1224     VALUE res = rb_funcall(callable, rb_intern("call"), 1, rd);
1225     return res == Qtrue;
1226   }
1227   SWIGINTERN void mark_Pool(void *ptr) {
1228     Pool *pool = ptr;
1229     if (pool->loadcallback == loadcallback && pool->loadcallbackdata) {
1230       VALUE callable = (VALUE)pool->loadcallbackdata;
1231       rb_gc_mark(callable);
1232     }
1233   }
1234 %}
1235   %typemap(in, numinputs=0) VALUE callable {
1236     $1 = rb_block_given_p() ? rb_block_proc() : 0;
1237   }
1238   void set_loadcallback(VALUE callable) {
1239     pool_setloadcallback($self, callable ? loadcallback : 0, (void *)callable);
1240   }
1241 #endif
1242
1243   ~Pool() {
1244     Pool_set_loadcallback($self, 0);
1245     pool_free($self);
1246   }
1247   disown_helper free() {
1248     Pool_set_loadcallback($self, 0);
1249     pool_free($self);
1250     return 0;
1251   }
1252   disown_helper disown() {
1253     return 0;
1254   }
1255   Id str2id(const char *str, bool create=1) {
1256     return pool_str2id($self, str, create);
1257   }
1258   %newobject Dep;
1259   Dep *Dep(const char *str, bool create=1) {
1260     Id id = pool_str2id($self, str, create);
1261     return new_Dep($self, id);
1262   }
1263   const char *id2str(Id id) {
1264     return pool_id2str($self, id);
1265   }
1266   const char *dep2str(Id id) {
1267     return pool_dep2str($self, id);
1268   }
1269   Id rel2id(Id name, Id evr, int flags, bool create=1) {
1270     return pool_rel2id($self, name, evr, flags, create);
1271   }
1272   Id id2langid(Id id, const char *lang, bool create=1) {
1273     return pool_id2langid($self, id, lang, create);
1274   }
1275   void setarch(const char *arch = 0) {
1276     struct utsname un;
1277     if (!arch) {
1278       if (uname(&un)) {
1279         perror("uname");
1280         return;
1281       }
1282       arch = un.machine;
1283     }
1284     pool_setarch($self, arch);
1285   }
1286   Repo *add_repo(const char *name) {
1287     return repo_create($self, name);
1288   }
1289   const char *lookup_str(Id entry, Id keyname) {
1290     return pool_lookup_str($self, entry, keyname);
1291   }
1292   Id lookup_id(Id entry, Id keyname) {
1293     return pool_lookup_id($self, entry, keyname);
1294   }
1295   unsigned long long lookup_num(Id entry, Id keyname, unsigned long long notfound = 0) {
1296     return pool_lookup_num($self, entry, keyname, notfound);
1297   }
1298   bool lookup_void(Id entry, Id keyname) {
1299     return pool_lookup_void($self, entry, keyname);
1300   }
1301   %newobject lookup_checksum;
1302   Chksum *lookup_checksum(Id entry, Id keyname) {
1303     Id type = 0;
1304     const unsigned char *b = pool_lookup_bin_checksum($self, entry, keyname, &type);
1305     return solv_chksum_create_from_bin(type, b);
1306   }
1307
1308   %newobject Dataiterator;
1309   Dataiterator *Dataiterator(Id key, const char *match = 0, int flags = 0) {
1310     return new_Dataiterator($self, 0, 0, key, match, flags);
1311   }
1312   %newobject Dataiterator_solvid;
1313   Dataiterator *Dataiterator_solvid(Id p, Id key, const char *match = 0, int flags = 0) {
1314     return new_Dataiterator($self, 0, p, key, match, flags);
1315   }
1316   const char *solvid2str(Id solvid) {
1317     return pool_solvid2str($self, solvid);
1318   }
1319   void addfileprovides() {
1320     pool_addfileprovides($self);
1321   }
1322   Queue addfileprovides_queue() {
1323     Queue r;
1324     queue_init(&r);
1325     pool_addfileprovides_queue($self, &r, 0);
1326     return r;
1327   }
1328   void createwhatprovides() {
1329     pool_createwhatprovides($self);
1330   }
1331
1332   %newobject id2solvable;
1333   XSolvable *id2solvable(Id id) {
1334     return new_XSolvable($self, id);
1335   }
1336   %newobject solvables;
1337   Pool_solvable_iterator * const solvables;
1338   %{
1339   SWIGINTERN Pool_solvable_iterator * Pool_solvables_get(Pool *pool) {
1340     return new_Pool_solvable_iterator(pool);
1341   }
1342   %}
1343   %newobject solvables_iter;
1344   Pool_solvable_iterator * solvables_iter() {
1345     return new_Pool_solvable_iterator($self);
1346   }
1347
1348   Repo *id2repo(Id id) {
1349     if (id < 1 || id >= $self->nrepos)
1350       return 0;
1351     return pool_id2repo($self, id);
1352   }
1353
1354   %newobject repos;
1355   Pool_repo_iterator * const repos;
1356   %{
1357   SWIGINTERN Pool_repo_iterator * Pool_repos_get(Pool *pool) {
1358     return new_Pool_repo_iterator(pool);
1359   }
1360   %}
1361   %newobject repos_iter;
1362   Pool_repo_iterator * repos_iter() {
1363     return new_Pool_repo_iterator($self);
1364   }
1365
1366   Repo *installed;
1367   const char * const errstr;
1368   %{
1369   SWIGINTERN void Pool_installed_set(Pool *pool, Repo *installed) {
1370     pool_set_installed(pool, installed);
1371   }
1372   Repo *Pool_installed_get(Pool *pool) {
1373     return pool->installed;
1374   }
1375   const char *Pool_errstr_get(Pool *pool) {
1376     return pool_errstr(pool);
1377   }
1378   %}
1379
1380   Queue matchprovidingids(const char *match, int flags) {
1381     Pool *pool = $self;
1382     Queue q;
1383     Id id;
1384     queue_init(&q);
1385     if (!flags) {
1386       for (id = 1; id < pool->ss.nstrings; id++)
1387         if (pool->whatprovides[id])
1388           queue_push(&q, id);
1389     } else {
1390       Datamatcher ma;
1391       if (!datamatcher_init(&ma, match, flags)) {
1392         for (id = 1; id < pool->ss.nstrings; id++)
1393           if (pool->whatprovides[id] && datamatcher_match(&ma, pool_id2str(pool, id)))
1394             queue_push(&q, id);
1395         datamatcher_free(&ma);
1396       }
1397     }
1398     return q;
1399   }
1400
1401   %newobject Job;
1402   Job *Job(int how, Id what) {
1403     return new_Job($self, how, what);
1404   }
1405
1406   %typemap(out) Queue whatprovides Queue2Array(XSolvable *, 1, new_XSolvable(arg1, id));
1407   %newobject whatprovides;
1408   Queue whatprovides(DepId dep) {
1409     Pool *pool = $self;
1410     Queue q;
1411     Id p, pp;
1412     queue_init(&q);
1413     FOR_PROVIDES(p, pp, dep)
1414       queue_push(&q, p);
1415     return q;
1416   }
1417
1418   Id towhatprovides(Queue q) {
1419     return pool_queuetowhatprovides($self, &q);
1420   }
1421
1422   %typemap(out) Queue whatmatchesdep Queue2Array(XSolvable *, 1, new_XSolvable(arg1, id));
1423   %newobject whatmatchesdep;
1424   Queue whatmatchesdep(Id keyname, DepId dep, Id marker = -1) {
1425     Queue q;
1426     queue_init(&q);
1427     pool_whatmatchesdep($self, keyname, dep, &q, marker);
1428     return q;
1429   }
1430
1431 #ifdef SWIGRUBY
1432   %rename("isknownarch?") isknownarch;
1433 #endif
1434   bool isknownarch(DepId id) {
1435     Pool *pool = $self;
1436     if (!id || id == ID_EMPTY)
1437       return 0;
1438     if (id == ARCH_SRC || id == ARCH_NOSRC || id == ARCH_NOARCH)
1439       return 1;
1440     if (pool->id2arch && (id > pool->lastarch || !pool->id2arch[id]))
1441       return 0;
1442     return 1;
1443   }
1444
1445   %newobject Solver;
1446   Solver *Solver() {
1447     return solver_create($self);
1448   }
1449
1450   %newobject Selection;
1451   Selection *Selection() {
1452     return new_Selection($self);
1453   }
1454   %newobject Selection_all;
1455   Selection *Selection_all(int setflags=0) {
1456     Selection *sel = new_Selection($self);
1457     queue_push2(&sel->q, SOLVER_SOLVABLE_ALL | setflags, 0);
1458     return sel;
1459   }
1460   %newobject select;
1461   Selection *select(const char *name, int flags) {
1462     Selection *sel = new_Selection($self);
1463     sel->flags = selection_make($self, &sel->q, name, flags);
1464     return sel;
1465   }
1466
1467   void setpooljobs_helper(Queue jobs) {
1468     queue_free(&$self->pooljobs);
1469     queue_init_clone(&$self->pooljobs, &jobs);
1470   }
1471   %typemap(out) Queue getpooljobs Queue2Array(Job *, 2, new_Job(arg1, id, idp[1]));
1472   %newobject getpooljobs;
1473   Queue getpooljobs() {
1474     Queue q;
1475     queue_init_clone(&q, &$self->pooljobs);
1476     return q;
1477   }
1478
1479 #if defined(SWIGPYTHON)
1480   %pythoncode {
1481     def setpooljobs(self, jobs):
1482       j = []
1483       for job in jobs: j += [job.how, job.what]
1484       self.setpooljobs_helper(j)
1485   }
1486 #endif
1487 #if defined(SWIGPERL)
1488   %perlcode {
1489     sub solv::Solver::setpooljobs {
1490       my ($self, $jobs) = @_;
1491       my @j = map {($_->{'how'}, $_->{'what'})} @$jobs;
1492       return $self->setpooljobs_helper(\@j);
1493     }
1494   }
1495 #endif
1496 #if defined(SWIGRUBY)
1497 %init %{
1498 rb_eval_string(
1499     "class Solv::Pool\n"
1500     "  def setpooljobs(jobs)\n"
1501     "    jl = []\n"
1502     "    jobs.each do |j| ; jl << j.how << j.what ; end\n"
1503     "    setpooljobs_helper(jl)\n"
1504     "  end\n"
1505     "end\n"
1506   );
1507 %}
1508 #endif
1509 }
1510
1511 %extend Repo {
1512   static const int REPO_REUSE_REPODATA = REPO_REUSE_REPODATA;
1513   static const int REPO_NO_INTERNALIZE = REPO_NO_INTERNALIZE;
1514   static const int REPO_LOCALPOOL = REPO_LOCALPOOL;
1515   static const int REPO_USE_LOADING = REPO_USE_LOADING;
1516   static const int REPO_EXTEND_SOLVABLES = REPO_EXTEND_SOLVABLES;
1517   static const int REPO_USE_ROOTDIR = REPO_USE_ROOTDIR;
1518   static const int REPO_NO_LOCATION = REPO_NO_LOCATION;
1519   static const int SOLV_ADD_NO_STUBS = SOLV_ADD_NO_STUBS;       /* repo_solv */
1520 #ifdef ENABLE_SUSEREPO
1521   static const int SUSETAGS_RECORD_SHARES = SUSETAGS_RECORD_SHARES;     /* repo_susetags */
1522 #endif
1523
1524   void free(bool reuseids = 0) {
1525     repo_free($self, reuseids);
1526   }
1527   void empty(bool reuseids = 0) {
1528     repo_empty($self, reuseids);
1529   }
1530 #ifdef SWIGRUBY
1531   %rename("isempty?") isempty;
1532 #endif
1533   bool isempty() {
1534     return !$self->nsolvables;
1535   }
1536   bool add_solv(const char *name, int flags = 0) {
1537     FILE *fp = fopen(name, "r");
1538     int r;
1539     if (!fp)
1540       return 0;
1541     r = repo_add_solv($self, fp, flags);
1542     fclose(fp);
1543     return r == 0;
1544   }
1545   bool add_solv(FILE *fp, int flags = 0) {
1546     return repo_add_solv($self, fp, flags) == 0;
1547   }
1548
1549   %newobject add_solvable;
1550   XSolvable *add_solvable() {
1551     Id solvid = repo_add_solvable($self);
1552     return new_XSolvable($self->pool, solvid);
1553   }
1554
1555 #ifdef ENABLE_RPMDB
1556   bool add_rpmdb(int flags = 0) {
1557     return repo_add_rpmdb($self, 0, flags) == 0;
1558   }
1559   bool add_rpmdb_reffp(FILE *reffp, int flags = 0) {
1560     return repo_add_rpmdb_reffp($self, reffp, flags) == 0;
1561   }
1562   %newobject add_rpm;
1563   XSolvable *add_rpm(const char *name, int flags = 0) {
1564     return new_XSolvable($self->pool, repo_add_rpm($self, name, flags));
1565   }
1566 #endif
1567 #ifdef ENABLE_PUBKEY
1568 #ifdef ENABLE_RPMDB
1569   bool add_rpmdb_pubkeys(int flags = 0) {
1570     return repo_add_rpmdb_pubkeys($self, flags) == 0;
1571   }
1572 #endif
1573   %newobject add_pubkey;
1574   XSolvable *add_pubkey(const char *keyfile, int flags = 0) {
1575     return new_XSolvable($self->pool, repo_add_pubkey($self, keyfile, flags));
1576   }
1577   bool add_keyring(FILE *fp, int flags = 0) {
1578     return repo_add_keyring($self, fp, flags);
1579   }
1580   bool add_keydir(const char *keydir, const char *suffix, int flags = 0) {
1581     return repo_add_keydir($self, keydir, suffix, flags);
1582   }
1583 #endif
1584 #ifdef ENABLE_RPMMD
1585   bool add_rpmmd(FILE *fp, const char *language, int flags = 0) {
1586     return repo_add_rpmmd($self, fp, language, flags) == 0;
1587   }
1588   bool add_repomdxml(FILE *fp, int flags = 0) {
1589     return repo_add_repomdxml($self, fp, flags) == 0;
1590   }
1591   bool add_updateinfoxml(FILE *fp, int flags = 0) {
1592     return repo_add_updateinfoxml($self, fp, flags) == 0;
1593   }
1594   bool add_deltainfoxml(FILE *fp, int flags = 0) {
1595     return repo_add_deltainfoxml($self, fp, flags) == 0;
1596   }
1597 #endif
1598 #ifdef ENABLE_DEBIAN
1599   bool add_debdb(int flags = 0) {
1600     return repo_add_debdb($self, flags) == 0;
1601   }
1602   bool add_debpackages(FILE *fp, int flags = 0) {
1603     return repo_add_debpackages($self, fp, flags) == 0;
1604   }
1605   %newobject add_deb;
1606   XSolvable *add_deb(const char *name, int flags = 0) {
1607     return new_XSolvable($self->pool, repo_add_deb($self, name, flags));
1608   }
1609 #endif
1610 #ifdef ENABLE_SUSEREPO
1611   bool add_susetags(FILE *fp, Id defvendor, const char *language, int flags = 0) {
1612     return repo_add_susetags($self, fp, defvendor, language, flags) == 0;
1613   }
1614   bool add_content(FILE *fp, int flags = 0) {
1615     return repo_add_content($self, fp, flags) == 0;
1616   }
1617   bool add_products(const char *proddir, int flags = 0) {
1618     return repo_add_products($self, proddir, flags) == 0;
1619   }
1620 #endif
1621 #ifdef ENABLE_MDKREPO
1622   bool add_mdk(FILE *fp, int flags = 0) {
1623     return repo_add_mdk($self, fp, flags) == 0;
1624   }
1625   bool add_mdk_info(FILE *fp, int flags = 0) {
1626     return repo_add_mdk_info($self, fp, flags) == 0;
1627   }
1628 #endif
1629 #ifdef ENABLE_ARCHREPO
1630   bool add_arch_repo(FILE *fp, int flags = 0) {
1631     return repo_add_arch_repo($self, fp, flags) == 0;
1632   }
1633   bool add_arch_local(const char *dir, int flags = 0) {
1634     return repo_add_arch_local($self, dir, flags) == 0;
1635   }
1636   %newobject add_arch_pkg;
1637   XSolvable *add_arch_pkg(const char *name, int flags = 0) {
1638     return new_XSolvable($self->pool, repo_add_arch_pkg($self, name, flags));
1639   }
1640 #endif
1641 #ifdef SUSE
1642   bool add_autopattern(int flags = 0) {
1643     return repo_add_autopattern($self, flags) == 0;
1644   }
1645 #endif
1646   void internalize() {
1647     repo_internalize($self);
1648   }
1649   bool write(FILE *fp) {
1650     return repo_write($self, fp) == 0;
1651   }
1652   /* HACK, remove if no longer needed! */
1653   bool write_first_repodata(FILE *fp) {
1654     int oldnrepodata = $self->nrepodata;
1655     int res;
1656     $self->nrepodata = oldnrepodata > 2 ? 2 : oldnrepodata;
1657     res = repo_write($self, fp);
1658     $self->nrepodata = oldnrepodata;
1659     return res == 0;
1660   }
1661
1662   %newobject Dataiterator;
1663   Dataiterator *Dataiterator(Id key, const char *match = 0, int flags = 0) {
1664     return new_Dataiterator($self->pool, $self, 0, key, match, flags);
1665   }
1666   %newobject Dataiterator_meta;
1667   Dataiterator *Dataiterator_meta(Id key, const char *match = 0, int flags = 0) {
1668     return new_Dataiterator($self->pool, $self, SOLVID_META, key, match, flags);
1669   }
1670
1671   Id const id;
1672   %{
1673   SWIGINTERN Id Repo_id_get(Repo *repo) {
1674     return repo->repoid;
1675   }
1676   %}
1677   %newobject solvables;
1678   Repo_solvable_iterator * const solvables;
1679   %{
1680   SWIGINTERN Repo_solvable_iterator * Repo_solvables_get(Repo *repo) {
1681     return new_Repo_solvable_iterator(repo);
1682   }
1683   %}
1684   %newobject meta;
1685   Datapos * const meta;
1686   %{
1687   SWIGINTERN Datapos * Repo_meta_get(Repo *repo) {
1688     Datapos *pos = solv_calloc(1, sizeof(*pos));
1689     pos->solvid = SOLVID_META;
1690     pos->repo = repo;
1691     return pos;
1692   }
1693   %}
1694
1695   %newobject solvables_iter;
1696   Repo_solvable_iterator *solvables_iter() {
1697     return new_Repo_solvable_iterator($self);
1698   }
1699
1700   %newobject add_repodata;
1701   XRepodata *add_repodata(int flags = 0) {
1702     Repodata *rd = repo_add_repodata($self, flags);
1703     return new_XRepodata($self, rd->repodataid);
1704   }
1705
1706   void create_stubs() {
1707     Repodata *data;
1708     if (!$self->nrepodata)
1709       return;
1710     data = repo_id2repodata($self, $self->nrepodata - 1);
1711     if (data->state != REPODATA_STUB)
1712       (void)repodata_create_stubs(data);
1713   }
1714 #ifdef SWIGRUBY
1715   %rename("iscontiguous?") iscontiguous;
1716 #endif
1717   bool iscontiguous() {
1718     int i;
1719     for (i = $self->start; i < $self->end; i++)
1720       if ($self->pool->solvables[i].repo != $self)
1721         return 0;
1722     return 1;
1723   }
1724   %newobject first_repodata;
1725   XRepodata *first_repodata() {
1726     Repodata *data;
1727     int i;
1728     if ($self->nrepodata < 2)
1729       return 0;
1730     /* make sure all repodatas but the first are extensions */
1731     data = repo_id2repodata($self, 1);
1732     if (data->loadcallback)
1733        return 0;
1734     for (i = 2; i < $self->nrepodata; i++)
1735       {
1736         data = repo_id2repodata($self, i);
1737         if (!data->loadcallback)
1738           return 0;       /* oops, not an extension */
1739       }
1740     return new_XRepodata($self, 1);
1741   }
1742
1743   %newobject Selection;
1744   Selection *Selection(int setflags=0) {
1745     Selection *sel = new_Selection($self->pool);
1746     setflags |= SOLVER_SETREPO;
1747     queue_push2(&sel->q, SOLVER_SOLVABLE_REPO | setflags, $self->repoid);
1748     return sel;
1749   }
1750
1751 #ifdef ENABLE_PUBKEY
1752   %newobject find_pubkey;
1753   XSolvable *find_pubkey(const char *keyid) {
1754     return new_XSolvable($self->pool, repo_find_pubkey($self, keyid));
1755   }
1756 #endif
1757
1758   bool __eq__(Repo *repo) {
1759     return $self == repo;
1760   }
1761   bool __ne__(Repo *repo) {
1762     return $self != repo;
1763   }
1764 #if defined(SWIGPERL)
1765   %rename("str") __str__;
1766 #endif
1767   %newobject __str__;
1768   const char *__str__() {
1769     char buf[20];
1770     if ($self->name)
1771       return solv_strdup($self->name);
1772     sprintf(buf, "Repo#%d", $self->repoid);
1773     return solv_strdup(buf);
1774   }
1775   %newobject __repr__;
1776   const char *__repr__() {
1777     char buf[20];
1778     if ($self->name)
1779       {
1780         sprintf(buf, "<Repo #%d ", $self->repoid);
1781         return solv_dupjoin(buf, $self->name, ">");
1782       }
1783     sprintf(buf, "<Repo #%d>", $self->repoid);
1784     return solv_strdup(buf);
1785   }
1786 }
1787
1788 %extend Dataiterator {
1789   static const int SEARCH_STRING = SEARCH_STRING;
1790   static const int SEARCH_STRINGSTART = SEARCH_STRINGSTART;
1791   static const int SEARCH_STRINGEND = SEARCH_STRINGEND;
1792   static const int SEARCH_SUBSTRING = SEARCH_SUBSTRING;
1793   static const int SEARCH_GLOB = SEARCH_GLOB;
1794   static const int SEARCH_REGEX = SEARCH_REGEX;
1795   static const int SEARCH_NOCASE = SEARCH_NOCASE;
1796   static const int SEARCH_FILES = SEARCH_FILES;
1797   static const int SEARCH_COMPLETE_FILELIST = SEARCH_COMPLETE_FILELIST;
1798   static const int SEARCH_CHECKSUMS = SEARCH_CHECKSUMS;
1799
1800   Dataiterator(Pool *pool, Repo *repo, Id p, Id key, const char *match, int flags) {
1801     Dataiterator *di = solv_calloc(1, sizeof(*di));
1802     dataiterator_init(di, pool, repo, p, key, match, flags);
1803     return di;
1804   }
1805   ~Dataiterator() {
1806     dataiterator_free($self);
1807     solv_free($self);
1808   }
1809 #if defined(SWIGPYTHON)
1810   %pythoncode {
1811     def __iter__(self): return self
1812   }
1813 #ifndef PYTHON3
1814   %rename("next") __next__();
1815 #endif
1816   %exception __next__ {
1817     $action
1818     if (!result) {
1819       PyErr_SetString(PyExc_StopIteration,"no more matches");
1820       return NULL;
1821     }
1822   }
1823 #endif
1824 #ifdef SWIGPERL
1825   perliter(solv::Dataiterator)
1826 #endif
1827   %newobject __next__;
1828   Datamatch *__next__() {
1829     Dataiterator *ndi;
1830     if (!dataiterator_step($self)) {
1831       return 0;
1832     }
1833     ndi = solv_calloc(1, sizeof(*ndi));
1834     dataiterator_init_clone(ndi, $self);
1835     dataiterator_strdup(ndi);
1836     return ndi;
1837   }
1838 #ifdef SWIGRUBY
1839   void each() {
1840     Datamatch *d;
1841     while ((d = Dataiterator___next__($self)) != 0) {
1842       rb_yield(SWIG_NewPointerObj(SWIG_as_voidptr(d), SWIGTYPE_p_Datamatch, SWIG_POINTER_OWN | 0));
1843     }
1844   }
1845 #endif
1846   void prepend_keyname(Id key) {
1847     dataiterator_prepend_keyname($self, key);
1848   }
1849   void skip_solvable() {
1850     dataiterator_skip_solvable($self);
1851   }
1852 }
1853
1854 %extend Datapos {
1855   Id lookup_id(Id keyname) {
1856     Pool *pool = $self->repo->pool;
1857     Datapos oldpos = pool->pos;
1858     Id r;
1859     pool->pos = *$self;
1860     r = pool_lookup_id(pool, SOLVID_POS, keyname);
1861     pool->pos = oldpos;
1862     return r;
1863   }
1864   const char *lookup_str(Id keyname) {
1865     Pool *pool = $self->repo->pool;
1866     Datapos oldpos = pool->pos;
1867     const char *r;
1868     pool->pos = *$self;
1869     r = pool_lookup_str(pool, SOLVID_POS, keyname);
1870     pool->pos = oldpos;
1871     return r;
1872   }
1873   unsigned long long lookup_num(Id keyname, unsigned long long notfound = 0) {
1874     Pool *pool = $self->repo->pool;
1875     Datapos oldpos = pool->pos;
1876     unsigned long long r;
1877     pool->pos = *$self;
1878     r = pool_lookup_num(pool, SOLVID_POS, keyname, notfound);
1879     pool->pos = oldpos;
1880     return r;
1881   }
1882   bool lookup_void(Id keyname) {
1883     Pool *pool = $self->repo->pool;
1884     Datapos oldpos = pool->pos;
1885     int r;
1886     pool->pos = *$self;
1887     r = pool_lookup_void(pool, SOLVID_POS, keyname);
1888     pool->pos = oldpos;
1889     return r;
1890   }
1891   %newobject lookup_checksum;
1892   Chksum *lookup_checksum(Id keyname) {
1893     Pool *pool = $self->repo->pool;
1894     Datapos oldpos = pool->pos;
1895     Id type = 0;
1896     const unsigned char *b;
1897     pool->pos = *$self;
1898     b = pool_lookup_bin_checksum(pool, SOLVID_POS, keyname, &type);
1899     pool->pos = oldpos;
1900     return solv_chksum_create_from_bin(type, b);
1901   }
1902   const char *lookup_deltaseq() {
1903     Pool *pool = $self->repo->pool;
1904     Datapos oldpos = pool->pos;
1905     const char *seq;
1906     pool->pos = *$self;
1907     seq = pool_lookup_str(pool, SOLVID_POS, DELTA_SEQ_NAME);
1908     if (seq) {
1909       seq = pool_tmpjoin(pool, seq, "-", pool_lookup_str(pool, SOLVID_POS, DELTA_SEQ_EVR));
1910       seq = pool_tmpappend(pool, seq, "-", pool_lookup_str(pool, SOLVID_POS, DELTA_SEQ_NUM));
1911     }
1912     pool->pos = oldpos;
1913     return seq;
1914   }
1915   const char *lookup_deltalocation(unsigned int *OUTPUT) {
1916     Pool *pool = $self->repo->pool;
1917     Datapos oldpos = pool->pos;
1918     const char *loc;
1919     pool->pos = *$self;
1920     loc = pool_lookup_deltalocation(pool, SOLVID_POS, OUTPUT);
1921     pool->pos = oldpos;
1922     return loc;
1923   }
1924   Queue lookup_idarray(Id keyname) {
1925     Pool *pool = $self->repo->pool;
1926     Datapos oldpos = pool->pos;
1927     Queue r;
1928     queue_init(&r);
1929     pool->pos = *$self;
1930     pool_lookup_idarray(pool, SOLVID_POS, keyname, &r);
1931     pool->pos = oldpos;
1932     return r;
1933   }
1934   %newobject Dataiterator;
1935   Dataiterator *Dataiterator(Id key, const char *match = 0, int flags = 0) {
1936     Pool *pool = $self->repo->pool;
1937     Datapos oldpos = pool->pos;
1938     Dataiterator *di;
1939     pool->pos = *$self;
1940     di = new_Dataiterator(pool, 0, SOLVID_POS, key, match, flags);
1941     pool->pos = oldpos;
1942     return di;
1943   }
1944 }
1945
1946 %extend Datamatch {
1947   ~Datamatch() {
1948     dataiterator_free($self);
1949     solv_free($self);
1950   }
1951   %newobject solvable;
1952   XSolvable * const solvable;
1953   Id const key_id;
1954   const char * const key_idstr;
1955   Id const type_id;
1956   const char * const type_idstr;
1957   Id const id;
1958   const char * const idstr;
1959   const char * const str;
1960   BinaryBlob const binary;
1961   unsigned long long const num;
1962   unsigned int const num2;
1963   %{
1964   SWIGINTERN XSolvable *Datamatch_solvable_get(Dataiterator *di) {
1965     return new_XSolvable(di->pool, di->solvid);
1966   }
1967   SWIGINTERN Id Datamatch_key_id_get(Dataiterator *di) {
1968     return di->key->name;
1969   }
1970   SWIGINTERN const char *Datamatch_key_idstr_get(Dataiterator *di) {
1971     return pool_id2str(di->pool, di->key->name);
1972   }
1973   SWIGINTERN Id Datamatch_type_id_get(Dataiterator *di) {
1974     return di->key->type;
1975   }
1976   SWIGINTERN const char *Datamatch_type_idstr_get(Dataiterator *di) {
1977     return pool_id2str(di->pool, di->key->type);
1978   }
1979   SWIGINTERN Id Datamatch_id_get(Dataiterator *di) {
1980     return di->kv.id;
1981   }
1982   SWIGINTERN const char *Datamatch_idstr_get(Dataiterator *di) {
1983    if (di->data && (di->key->type == REPOKEY_TYPE_DIR || di->key->type == REPOKEY_TYPE_DIRSTRARRAY || di->key->type == REPOKEY_TYPE_DIRNUMNUMARRAY))
1984       return repodata_dir2str(di->data,  di->kv.id, 0);
1985     if (di->data && di->data->localpool)
1986       return stringpool_id2str(&di->data->spool, di->kv.id);
1987     return pool_id2str(di->pool, di->kv.id);
1988   }
1989   SWIGINTERN const char * const Datamatch_str_get(Dataiterator *di) {
1990     return di->kv.str;
1991   }
1992   SWIGINTERN BinaryBlob Datamatch_binary_get(Dataiterator *di) {
1993     BinaryBlob bl;
1994     bl.data = 0;
1995     bl.len = 0;
1996     if (di->key->type == REPOKEY_TYPE_BINARY)
1997       {
1998         bl.data = di->kv.str;
1999         bl.len = di->kv.num;
2000       }
2001     else if ((bl.len = solv_chksum_len(di->key->type)) != 0)
2002       bl.data = di->kv.str;
2003     return bl;
2004   }
2005   SWIGINTERN unsigned long long Datamatch_num_get(Dataiterator *di) {
2006    if (di->key->type == REPOKEY_TYPE_NUM)
2007      return SOLV_KV_NUM64(&di->kv);
2008    return di->kv.num;
2009   }
2010   SWIGINTERN unsigned int Datamatch_num2_get(Dataiterator *di) {
2011     return di->kv.num2;
2012   }
2013   %}
2014   %newobject pos;
2015   Datapos *pos() {
2016     Pool *pool = $self->pool;
2017     Datapos *pos, oldpos = pool->pos;
2018     dataiterator_setpos($self);
2019     pos = solv_calloc(1, sizeof(*pos));
2020     *pos = pool->pos;
2021     pool->pos = oldpos;
2022     return pos;
2023   }
2024   %newobject parentpos;
2025   Datapos *parentpos() {
2026     Pool *pool = $self->pool;
2027     Datapos *pos, oldpos = pool->pos;
2028     dataiterator_setpos_parent($self);
2029     pos = solv_calloc(1, sizeof(*pos));
2030     *pos = pool->pos;
2031     pool->pos = oldpos;
2032     return pos;
2033   }
2034 #if defined(SWIGPERL)
2035   /* cannot use str here because swig reports a bogus conflict... */
2036   %rename("stringify") __str__;
2037   %perlcode {
2038     *solv::Datamatch::str = *solvc::Datamatch_stringify;
2039   }
2040 #endif
2041   const char *__str__() {
2042     KeyValue kv = $self->kv;
2043     const char *str = repodata_stringify($self->pool, $self->data, $self->key, &kv, SEARCH_FILES | SEARCH_CHECKSUMS);
2044     return str ? str : "";
2045   }
2046 }
2047
2048 %extend Pool_solvable_iterator {
2049   Pool_solvable_iterator(Pool *pool) {
2050     Pool_solvable_iterator *s;
2051     s = solv_calloc(1, sizeof(*s));
2052     s->pool = pool;
2053     return s;
2054   }
2055 #if defined(SWIGPYTHON)
2056   %pythoncode {
2057     def __iter__(self): return self
2058   }
2059 #ifndef PYTHON3
2060   %rename("next") __next__();
2061 #endif
2062   %exception __next__ {
2063     $action
2064     if (!result) {
2065       PyErr_SetString(PyExc_StopIteration,"no more matches");
2066       return NULL;
2067     }
2068   }
2069 #endif
2070 #ifdef SWIGPERL
2071   perliter(solv::Pool_solvable_iterator)
2072 #endif
2073   %newobject __next__;
2074   XSolvable *__next__() {
2075     Pool *pool = $self->pool;
2076     if ($self->id >= pool->nsolvables)
2077       return 0;
2078     while (++$self->id < pool->nsolvables)
2079       if (pool->solvables[$self->id].repo)
2080         return new_XSolvable(pool, $self->id);
2081     return 0;
2082   }
2083 #ifdef SWIGRUBY
2084   void each() {
2085     XSolvable *n;
2086     while ((n = Pool_solvable_iterator___next__($self)) != 0) {
2087       rb_yield(SWIG_NewPointerObj(SWIG_as_voidptr(n), SWIGTYPE_p_XSolvable, SWIG_POINTER_OWN | 0));
2088     }
2089   }
2090 #endif
2091   %newobject __getitem__;
2092   XSolvable *__getitem__(Id key) {
2093     Pool *pool = $self->pool;
2094     if (key > 0 && key < pool->nsolvables && pool->solvables[key].repo)
2095       return new_XSolvable(pool, key);
2096     return 0;
2097   }
2098   int __len__() {
2099     return $self->pool->nsolvables;
2100   }
2101 }
2102
2103 %extend Pool_repo_iterator {
2104   Pool_repo_iterator(Pool *pool) {
2105     Pool_repo_iterator *s;
2106     s = solv_calloc(1, sizeof(*s));
2107     s->pool = pool;
2108     return s;
2109   }
2110 #if defined(SWIGPYTHON)
2111   %pythoncode {
2112     def __iter__(self): return self
2113   }
2114 #ifndef PYTHON3
2115   %rename("next") __next__();
2116 #endif
2117   %exception __next__ {
2118     $action
2119     if (!result) {
2120       PyErr_SetString(PyExc_StopIteration,"no more matches");
2121       return NULL;
2122     }
2123   }
2124 #endif
2125 #ifdef SWIGPERL
2126   perliter(solv::Pool_repo_iterator)
2127 #endif
2128   %newobject __next__;
2129   Repo *__next__() {
2130     Pool *pool = $self->pool;
2131     if ($self->id >= pool->nrepos)
2132       return 0;
2133     while (++$self->id < pool->nrepos) {
2134       Repo *r = pool_id2repo(pool, $self->id);
2135       if (r)
2136         return r;
2137     }
2138     return 0;
2139   }
2140 #ifdef SWIGRUBY
2141   void each() {
2142     Repo *n;
2143     while ((n = Pool_repo_iterator___next__($self)) != 0) {
2144       rb_yield(SWIG_NewPointerObj(SWIG_as_voidptr(n), SWIGTYPE_p_Repo, SWIG_POINTER_OWN | 0));
2145     }
2146   }
2147 #endif
2148   Repo *__getitem__(Id key) {
2149     Pool *pool = $self->pool;
2150     if (key > 0 && key < pool->nrepos)
2151       return pool_id2repo(pool, key);
2152     return 0;
2153   }
2154   int __len__() {
2155     return $self->pool->nrepos;
2156   }
2157 }
2158
2159 %extend Repo_solvable_iterator {
2160   Repo_solvable_iterator(Repo *repo) {
2161     Repo_solvable_iterator *s;
2162     s = solv_calloc(1, sizeof(*s));
2163     s->repo = repo;
2164     return s;
2165   }
2166 #if defined(SWIGPYTHON)
2167   %pythoncode {
2168     def __iter__(self): return self
2169   }
2170 #ifndef PYTHON3
2171   %rename("next") __next__();
2172 #endif
2173   %exception __next__ {
2174     $action
2175     if (!result) {
2176       PyErr_SetString(PyExc_StopIteration,"no more matches");
2177       return NULL;
2178     }
2179   }
2180 #endif
2181 #ifdef SWIGPERL
2182   perliter(solv::Repo_solvable_iterator)
2183 #endif
2184   %newobject __next__;
2185   XSolvable *__next__() {
2186     Repo *repo = $self->repo;
2187     Pool *pool = repo->pool;
2188     if (repo->start > 0 && $self->id < repo->start)
2189       $self->id = repo->start - 1;
2190     if ($self->id >= repo->end)
2191       return 0;
2192     while (++$self->id < repo->end)
2193       if (pool->solvables[$self->id].repo == repo)
2194         return new_XSolvable(pool, $self->id);
2195     return 0;
2196   }
2197 #ifdef SWIGRUBY
2198   void each() {
2199     XSolvable *n;
2200     while ((n = Repo_solvable_iterator___next__($self)) != 0) {
2201       rb_yield(SWIG_NewPointerObj(SWIG_as_voidptr(n), SWIGTYPE_p_XSolvable, SWIG_POINTER_OWN | 0));
2202     }
2203   }
2204 #endif
2205   %newobject __getitem__;
2206   XSolvable *__getitem__(Id key) {
2207     Repo *repo = $self->repo;
2208     Pool *pool = repo->pool;
2209     if (key > 0 && key < pool->nsolvables && pool->solvables[key].repo == repo)
2210       return new_XSolvable(pool, key);
2211     return 0;
2212   }
2213   int __len__() {
2214     return $self->repo->pool->nsolvables;
2215   }
2216 }
2217
2218 %extend Dep {
2219   Dep(Pool *pool, Id id) {
2220     Dep *s;
2221     if (!id)
2222       return 0;
2223     s = solv_calloc(1, sizeof(*s));
2224     s->pool = pool;
2225     s->id = id;
2226     return s;
2227   }
2228   %newobject Rel;
2229   Dep *Rel(int flags, DepId evrid, bool create=1) {
2230     Id id = pool_rel2id($self->pool, $self->id, evrid, flags, create);
2231     if (!id)
2232       return 0;
2233     return new_Dep($self->pool, id);
2234   }
2235   %newobject Selection_name;
2236   Selection *Selection_name(int setflags=0) {
2237     Selection *sel = new_Selection($self->pool);
2238     if (ISRELDEP($self->id)) {
2239       Reldep *rd = GETRELDEP($self->pool, $self->id);
2240       if (rd->flags == REL_EQ) {
2241         setflags |= $self->pool->disttype == DISTTYPE_DEB || strchr(pool_id2str($self->pool, rd->evr), '-') != 0 ? SOLVER_SETEVR : SOLVER_SETEV;
2242         if (ISRELDEP(rd->name))
2243           rd = GETRELDEP($self->pool, rd->name);
2244       }
2245       if (rd->flags == REL_ARCH)
2246         setflags |= SOLVER_SETARCH;
2247     }
2248     queue_push2(&sel->q, SOLVER_SOLVABLE_NAME | setflags, $self->id);
2249     return sel;
2250   }
2251   %newobject Selection_provides;
2252   Selection *Selection_provides(int setflags=0) {
2253     Selection *sel = new_Selection($self->pool);
2254     if (ISRELDEP($self->id)) {
2255       Reldep *rd = GETRELDEP($self->pool, $self->id);
2256       if (rd->flags == REL_ARCH)
2257         setflags |= SOLVER_SETARCH;
2258     }
2259     queue_push2(&sel->q, SOLVER_SOLVABLE_PROVIDES | setflags, $self->id);
2260     return sel;
2261   }
2262   const char *str() {
2263     return pool_dep2str($self->pool, $self->id);
2264   }
2265   bool __eq__(Dep *s) {
2266     return $self->pool == s->pool && $self->id == s->id;
2267   }
2268   bool __ne__(Dep *s) {
2269     return !Dep___eq__($self, s);
2270   }
2271 #if defined(SWIGPERL)
2272   %rename("str") __str__;
2273 #endif
2274   const char *__str__() {
2275     return pool_dep2str($self->pool, $self->id);
2276   }
2277   %newobject __repr__;
2278   const char *__repr__() {
2279     char buf[20];
2280     sprintf(buf, "<Id #%d ", $self->id);
2281     return solv_dupjoin(buf, pool_dep2str($self->pool, $self->id), ">");
2282   }
2283 }
2284
2285 %extend XSolvable {
2286   XSolvable(Pool *pool, Id id) {
2287     XSolvable *s;
2288     if (!id || id >= pool->nsolvables)
2289       return 0;
2290     s = solv_calloc(1, sizeof(*s));
2291     s->pool = pool;
2292     s->id = id;
2293     return s;
2294   }
2295   const char *str() {
2296     return pool_solvid2str($self->pool, $self->id);
2297   }
2298   const char *lookup_str(Id keyname) {
2299     return pool_lookup_str($self->pool, $self->id, keyname);
2300   }
2301   Id lookup_id(Id keyname) {
2302     return pool_lookup_id($self->pool, $self->id, keyname);
2303   }
2304   unsigned long long lookup_num(Id keyname, unsigned long long notfound = 0) {
2305     return pool_lookup_num($self->pool, $self->id, keyname, notfound);
2306   }
2307   bool lookup_void(Id keyname) {
2308     return pool_lookup_void($self->pool, $self->id, keyname);
2309   }
2310   %newobject lookup_checksum;
2311   Chksum *lookup_checksum(Id keyname) {
2312     Id type = 0;
2313     const unsigned char *b = pool_lookup_bin_checksum($self->pool, $self->id, keyname, &type);
2314     return solv_chksum_create_from_bin(type, b);
2315   }
2316   Queue lookup_idarray(Id keyname, Id marker = -1) {
2317     Solvable *s = $self->pool->solvables + $self->id;
2318     Queue r;
2319     queue_init(&r);
2320     solvable_lookup_deparray(s, keyname, &r, marker);
2321     return r;
2322   }
2323   %typemap(out) Queue lookup_deparray Queue2Array(Dep *, 1, new_Dep(arg1->pool, id));
2324   %newobject lookup_deparray;
2325   Queue lookup_deparray(Id keyname, Id marker = -1) {
2326     Solvable *s = $self->pool->solvables + $self->id;
2327     Queue r;
2328     queue_init(&r);
2329     solvable_lookup_deparray(s, keyname, &r, marker);
2330     return r;
2331   }
2332   const char *lookup_location(unsigned int *OUTPUT) {
2333     return solvable_lookup_location($self->pool->solvables + $self->id, OUTPUT);
2334   }
2335   %newobject Dataiterator;
2336   Dataiterator *Dataiterator(Id key, const char *match = 0, int flags = 0) {
2337     return new_Dataiterator($self->pool, 0, $self->id, key, match, flags);
2338   }
2339 #ifdef SWIGRUBY
2340   %rename("installable?") installable;
2341 #endif
2342   bool installable() {
2343     return pool_installable($self->pool, pool_id2solvable($self->pool, $self->id));
2344   }
2345 #ifdef SWIGRUBY
2346   %rename("isinstalled?") isinstalled;
2347 #endif
2348   bool isinstalled() {
2349     Pool *pool = $self->pool;
2350     return pool->installed && pool_id2solvable(pool, $self->id)->repo == pool->installed;
2351   }
2352
2353   const char *name;
2354   %{
2355     SWIGINTERN void XSolvable_name_set(XSolvable *xs, const char *name) {
2356       Pool *pool = xs->pool;
2357       pool->solvables[xs->id].name = pool_str2id(pool, name, 1);
2358     }
2359     SWIGINTERN const char *XSolvable_name_get(XSolvable *xs) {
2360       Pool *pool = xs->pool;
2361       return pool_id2str(pool, pool->solvables[xs->id].name);
2362     }
2363   %}
2364   Id nameid;
2365   %{
2366     SWIGINTERN void XSolvable_nameid_set(XSolvable *xs, Id nameid) {
2367       xs->pool->solvables[xs->id].name = nameid;
2368     }
2369     SWIGINTERN Id XSolvable_nameid_get(XSolvable *xs) {
2370       return xs->pool->solvables[xs->id].name;
2371     }
2372   %}
2373   const char *evr;
2374   %{
2375     SWIGINTERN void XSolvable_evr_set(XSolvable *xs, const char *evr) {
2376       Pool *pool = xs->pool;
2377       pool->solvables[xs->id].evr = pool_str2id(pool, evr, 1);
2378     }
2379     SWIGINTERN const char *XSolvable_evr_get(XSolvable *xs) {
2380       Pool *pool = xs->pool;
2381       return pool_id2str(pool, pool->solvables[xs->id].evr);
2382     }
2383   %}
2384   Id evrid;
2385   %{
2386     SWIGINTERN void XSolvable_evrid_set(XSolvable *xs, Id evrid) {
2387       xs->pool->solvables[xs->id].evr = evrid;
2388     }
2389     SWIGINTERN Id XSolvable_evrid_get(XSolvable *xs) {
2390       return xs->pool->solvables[xs->id].evr;
2391     }
2392   %}
2393   const char *arch;
2394   %{
2395     SWIGINTERN void XSolvable_arch_set(XSolvable *xs, const char *arch) {
2396       Pool *pool = xs->pool;
2397       pool->solvables[xs->id].arch = pool_str2id(pool, arch, 1);
2398     }
2399     SWIGINTERN const char *XSolvable_arch_get(XSolvable *xs) {
2400       Pool *pool = xs->pool;
2401       return pool_id2str(pool, pool->solvables[xs->id].arch);
2402     }
2403   %}
2404   Id archid;
2405   %{
2406     SWIGINTERN void XSolvable_archid_set(XSolvable *xs, Id archid) {
2407       xs->pool->solvables[xs->id].arch = archid;
2408     }
2409     SWIGINTERN Id XSolvable_archid_get(XSolvable *xs) {
2410       return xs->pool->solvables[xs->id].arch;
2411     }
2412   %}
2413   const char *vendor;
2414   %{
2415     SWIGINTERN void XSolvable_vendor_set(XSolvable *xs, const char *vendor) {
2416       Pool *pool = xs->pool;
2417       pool->solvables[xs->id].vendor = pool_str2id(pool, vendor, 1);
2418     }
2419     SWIGINTERN const char *XSolvable_vendor_get(XSolvable *xs) {
2420       Pool *pool = xs->pool;
2421       return pool_id2str(pool, pool->solvables[xs->id].vendor);
2422     }
2423   %}
2424   Id vendorid;
2425   %{
2426     SWIGINTERN void XSolvable_vendorid_set(XSolvable *xs, Id vendorid) {
2427       xs->pool->solvables[xs->id].vendor = vendorid;
2428     }
2429     SWIGINTERN Id XSolvable_vendorid_get(XSolvable *xs) {
2430       return xs->pool->solvables[xs->id].vendor;
2431     }
2432   %}
2433   Repo * const repo;
2434   %{
2435     SWIGINTERN Repo *XSolvable_repo_get(XSolvable *xs) {
2436       return xs->pool->solvables[xs->id].repo;
2437     }
2438   %}
2439
2440   /* old interface, please use the generic add_deparray instead */
2441   void add_provides(DepId id, Id marker = -1) {
2442     Solvable *s = $self->pool->solvables + $self->id;
2443     marker = solv_depmarker(SOLVABLE_PROVIDES, marker);
2444     s->provides = repo_addid_dep(s->repo, s->provides, id, marker);
2445   }
2446   void add_obsoletes(DepId id) {
2447     Solvable *s = $self->pool->solvables + $self->id;
2448     s->obsoletes = repo_addid_dep(s->repo, s->obsoletes, id, 0);
2449   }
2450   void add_conflicts(DepId id) {
2451     Solvable *s = $self->pool->solvables + $self->id;
2452     s->conflicts = repo_addid_dep(s->repo, s->conflicts, id, 0);
2453   }
2454   void add_requires(DepId id, Id marker = -1) {
2455     Solvable *s = $self->pool->solvables + $self->id;
2456     marker = solv_depmarker(SOLVABLE_REQUIRES, marker);
2457     s->requires = repo_addid_dep(s->repo, s->requires, id, marker);
2458   }
2459   void add_recommends(DepId id) {
2460     Solvable *s = $self->pool->solvables + $self->id;
2461     s->recommends = repo_addid_dep(s->repo, s->recommends, id, 0);
2462   }
2463   void add_suggests(DepId id) {
2464     Solvable *s = $self->pool->solvables + $self->id;
2465     s->suggests = repo_addid_dep(s->repo, s->suggests, id, 0);
2466   }
2467   void add_supplements(DepId id) {
2468     Solvable *s = $self->pool->solvables + $self->id;
2469     s->supplements = repo_addid_dep(s->repo, s->supplements, id, 0);
2470   }
2471   void add_enhances(DepId id) {
2472     Solvable *s = $self->pool->solvables + $self->id;
2473     s->enhances = repo_addid_dep(s->repo, s->enhances, id, 0);
2474   }
2475
2476   void unset(Id keyname) {
2477     Solvable *s = $self->pool->solvables + $self->id;
2478     repo_unset(s->repo, $self->id, keyname);
2479   }
2480
2481   void add_deparray(Id keyname, DepId id, Id marker = -1) {
2482     Solvable *s = $self->pool->solvables + $self->id;
2483     solvable_add_deparray(s, keyname, id, marker);
2484   }
2485
2486   %newobject Selection;
2487   Selection *Selection(int setflags=0) {
2488     Selection *sel = new_Selection($self->pool);
2489     queue_push2(&sel->q, SOLVER_SOLVABLE | setflags, $self->id);
2490     return sel;
2491   }
2492
2493 #ifdef SWIGRUBY
2494   %rename("identical?") identical;
2495 #endif
2496   bool identical(XSolvable *s2) {
2497     return solvable_identical($self->pool->solvables + $self->id, s2->pool->solvables + s2->id);
2498   }
2499   int evrcmp(XSolvable *s2) {
2500     return pool_evrcmp($self->pool, $self->pool->solvables[$self->id].evr, s2->pool->solvables[s2->id].evr, EVRCMP_COMPARE);
2501   }
2502
2503   bool __eq__(XSolvable *s) {
2504     return $self->pool == s->pool && $self->id == s->id;
2505   }
2506   bool __ne__(XSolvable *s) {
2507     return !XSolvable___eq__($self, s);
2508   }
2509 #if defined(SWIGPERL)
2510   %rename("str") __str__;
2511 #endif
2512   const char *__str__() {
2513     return pool_solvid2str($self->pool, $self->id);
2514   }
2515   %newobject __repr__;
2516   const char *__repr__() {
2517     char buf[20];
2518     sprintf(buf, "<Solvable #%d ", $self->id);
2519     return solv_dupjoin(buf, pool_solvid2str($self->pool, $self->id), ">");
2520   }
2521 }
2522
2523 %extend Problem {
2524   Problem(Solver *solv, Id id) {
2525     Problem *p;
2526     p = solv_calloc(1, sizeof(*p));
2527     p->solv = solv;
2528     p->id = id;
2529     return p;
2530   }
2531   %newobject findproblemrule;
2532   XRule *findproblemrule() {
2533     Id r = solver_findproblemrule($self->solv, $self->id);
2534     return new_XRule($self->solv, r);
2535   }
2536   %newobject findallproblemrules;
2537   %typemap(out) Queue findallproblemrules Queue2Array(XRule *, 1, new_XRule(arg1->solv, id));
2538   Queue findallproblemrules(int unfiltered=0) {
2539     Solver *solv = $self->solv;
2540     Id probr;
2541     int i, j;
2542     Queue q;
2543     queue_init(&q);
2544     solver_findallproblemrules(solv, $self->id, &q);
2545     if (!unfiltered)
2546       {
2547         for (i = j = 0; i < q.count; i++)
2548           {
2549             SolverRuleinfo rclass;
2550             probr = q.elements[i];
2551             rclass = solver_ruleclass(solv, probr);
2552             if (rclass == SOLVER_RULE_UPDATE || rclass == SOLVER_RULE_JOB)
2553               continue;
2554             q.elements[j++] = probr;
2555           }
2556         if (j)
2557           queue_truncate(&q, j);
2558       }
2559     return q;
2560   }
2561   int solution_count() {
2562     return solver_solution_count($self->solv, $self->id);
2563   }
2564   %typemap(out) Queue solutions Queue2Array(Solution *, 1, new_Solution(arg1, id));
2565   %newobject solutions;
2566   Queue solutions() {
2567     Queue q;
2568     int i, cnt;
2569     queue_init(&q);
2570     cnt = solver_solution_count($self->solv, $self->id);
2571     for (i = 1; i <= cnt; i++)
2572       queue_push(&q, i);
2573     return q;
2574   }
2575 #if defined(SWIGPERL)
2576   %rename("str") __str__;
2577 #endif
2578   const char *__str__() {
2579     return solver_problem2str($self->solv, $self->id);
2580   }
2581 }
2582
2583 %extend Solution {
2584   Solution(Problem *p, Id id) {
2585     Solution *s;
2586     s = solv_calloc(1, sizeof(*s));
2587     s->solv = p->solv;
2588     s->problemid = p->id;
2589     s->id = id;
2590     return s;
2591   }
2592   int element_count() {
2593     return solver_solutionelement_count($self->solv, $self->problemid, $self->id);
2594   }
2595
2596   %typemap(out) Queue elements Queue2Array(Solutionelement *, 4, new_Solutionelement(arg1->solv, arg1->problemid, arg1->id, id, idp[1], idp[2], idp[3]));
2597   %newobject elements;
2598   Queue elements(bool expandreplaces=0) {
2599     Queue q;
2600     int i, cnt;
2601     queue_init(&q);
2602     cnt = solver_solutionelement_count($self->solv, $self->problemid, $self->id);
2603     for (i = 1; i <= cnt; i++)
2604       {
2605         Id p, rp, type;
2606         solver_next_solutionelement($self->solv, $self->problemid, $self->id, i - 1, &p, &rp);
2607         if (p > 0) {
2608           type = rp ? SOLVER_SOLUTION_REPLACE : SOLVER_SOLUTION_ERASE;
2609         } else {
2610           type = p;
2611           p = rp;
2612           rp = 0;
2613         }
2614         if (type == SOLVER_SOLUTION_REPLACE && expandreplaces) {
2615           int illegal = policy_is_illegal(self->solv, self->solv->pool->solvables + p, self->solv->pool->solvables + rp, 0);
2616           if (illegal) {
2617             if ((illegal & POLICY_ILLEGAL_DOWNGRADE) != 0) {
2618               queue_push2(&q, i, SOLVER_SOLUTION_REPLACE_DOWNGRADE);
2619               queue_push2(&q, p, rp);
2620             }
2621             if ((illegal & POLICY_ILLEGAL_ARCHCHANGE) != 0) {
2622               queue_push2(&q, i, SOLVER_SOLUTION_REPLACE_ARCHCHANGE);
2623               queue_push2(&q, p, rp);
2624             }
2625             if ((illegal & POLICY_ILLEGAL_VENDORCHANGE) != 0) {
2626               queue_push2(&q, i, SOLVER_SOLUTION_REPLACE_VENDORCHANGE);
2627               queue_push2(&q, p, rp);
2628             }
2629             if ((illegal & POLICY_ILLEGAL_NAMECHANGE) != 0) {
2630               queue_push2(&q, i, SOLVER_SOLUTION_REPLACE_NAMECHANGE);
2631               queue_push2(&q, p, rp);
2632             }
2633             continue;
2634           }
2635         }
2636         queue_push2(&q, i, type);
2637         queue_push2(&q, p, rp);
2638       }
2639     return q;
2640   }
2641 }
2642
2643 %extend Solutionelement {
2644   Solutionelement(Solver *solv, Id problemid, Id solutionid, Id id, Id type, Id p, Id rp) {
2645     Solutionelement *e;
2646     e = solv_calloc(1, sizeof(*e));
2647     e->solv = solv;
2648     e->problemid = problemid;
2649     e->solutionid = id;
2650     e->id = id;
2651     e->type = type;
2652     e->p = p;
2653     e->rp = rp;
2654     return e;
2655   }
2656   const char *str() {
2657     Id p = $self->type;
2658     Id rp = $self->p;
2659     int illegal = 0;
2660     if (p == SOLVER_SOLUTION_ERASE)
2661       {
2662         p = rp;
2663         rp = 0;
2664       }
2665     else if (p == SOLVER_SOLUTION_REPLACE)
2666       {
2667         p = rp;
2668         rp = $self->rp;
2669       }
2670     else if (p == SOLVER_SOLUTION_REPLACE_DOWNGRADE)
2671       illegal = POLICY_ILLEGAL_DOWNGRADE;
2672     else if (p == SOLVER_SOLUTION_REPLACE_ARCHCHANGE)
2673       illegal = POLICY_ILLEGAL_ARCHCHANGE;
2674     else if (p == SOLVER_SOLUTION_REPLACE_VENDORCHANGE)
2675       illegal = POLICY_ILLEGAL_VENDORCHANGE;
2676     else if (p == SOLVER_SOLUTION_REPLACE_NAMECHANGE)
2677       illegal = POLICY_ILLEGAL_NAMECHANGE;
2678     if (illegal)
2679       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);
2680     return solver_solutionelement2str($self->solv, p, rp);
2681   }
2682   %typemap(out) Queue replaceelements Queue2Array(Solutionelement *, 1, new_Solutionelement(arg1->solv, arg1->problemid, arg1->solutionid, arg1->id, id, arg1->p, arg1->rp));
2683   %newobject replaceelements;
2684   Queue replaceelements() {
2685     Queue q;
2686     int illegal;
2687
2688     queue_init(&q);
2689     if ($self->type != SOLVER_SOLUTION_REPLACE || $self->p <= 0 || $self->rp <= 0)
2690       illegal = 0;
2691     else
2692       illegal = policy_is_illegal($self->solv, $self->solv->pool->solvables + $self->p, $self->solv->pool->solvables + $self->rp, 0);
2693     if ((illegal & POLICY_ILLEGAL_DOWNGRADE) != 0)
2694       queue_push(&q, SOLVER_SOLUTION_REPLACE_DOWNGRADE);
2695     if ((illegal & POLICY_ILLEGAL_ARCHCHANGE) != 0)
2696       queue_push(&q, SOLVER_SOLUTION_REPLACE_ARCHCHANGE);
2697     if ((illegal & POLICY_ILLEGAL_VENDORCHANGE) != 0)
2698       queue_push(&q, SOLVER_SOLUTION_REPLACE_VENDORCHANGE);
2699     if ((illegal & POLICY_ILLEGAL_NAMECHANGE) != 0)
2700       queue_push(&q, SOLVER_SOLUTION_REPLACE_NAMECHANGE);
2701     if (!q.count)
2702       queue_push(&q, $self->type);
2703     return q;
2704   }
2705   int illegalreplace() {
2706     if ($self->type != SOLVER_SOLUTION_REPLACE || $self->p <= 0 || $self->rp <= 0)
2707       return 0;
2708     return policy_is_illegal($self->solv, $self->solv->pool->solvables + $self->p, $self->solv->pool->solvables + $self->rp, 0);
2709   }
2710   %newobject solvable;
2711   XSolvable * const solvable;
2712   %newobject replacement;
2713   XSolvable * const replacement;
2714   int const jobidx;
2715   %{
2716     SWIGINTERN XSolvable *Solutionelement_solvable_get(Solutionelement *e) {
2717       return new_XSolvable(e->solv->pool, e->p);
2718     }
2719     SWIGINTERN XSolvable *Solutionelement_replacement_get(Solutionelement *e) {
2720       return new_XSolvable(e->solv->pool, e->rp);
2721     }
2722     SWIGINTERN int Solutionelement_jobidx_get(Solutionelement *e) {
2723       if (e->type != SOLVER_SOLUTION_JOB && e->type != SOLVER_SOLUTION_POOLJOB)
2724         return -1;
2725       return (e->p - 1) / 2;
2726     }
2727   %}
2728   %newobject Job;
2729   Job *Job() {
2730     Id extraflags = solver_solutionelement_extrajobflags($self->solv, $self->problemid, $self->solutionid);
2731     if ($self->type == SOLVER_SOLUTION_JOB || SOLVER_SOLUTION_POOLJOB)
2732       return new_Job($self->solv->pool, SOLVER_NOOP, 0);
2733     if ($self->type == SOLVER_SOLUTION_INFARCH || $self->type == SOLVER_SOLUTION_DISTUPGRADE || $self->type == SOLVER_SOLUTION_BEST)
2734       return new_Job($self->solv->pool, SOLVER_INSTALL|SOLVER_SOLVABLE|SOLVER_NOTBYUSER|extraflags, $self->p);
2735     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)
2736       return new_Job($self->solv->pool, SOLVER_INSTALL|SOLVER_SOLVABLE|SOLVER_NOTBYUSER|extraflags, $self->rp);
2737     if ($self->type == SOLVER_SOLUTION_ERASE)
2738       return new_Job($self->solv->pool, SOLVER_ERASE|SOLVER_SOLVABLE|extraflags, $self->p);
2739     return 0;
2740   }
2741 }
2742
2743 %extend Solver {
2744   static const int SOLVER_RULE_UNKNOWN = SOLVER_RULE_UNKNOWN;
2745   static const int SOLVER_RULE_PKG = SOLVER_RULE_PKG;
2746   static const int SOLVER_RULE_PKG_NOT_INSTALLABLE = SOLVER_RULE_PKG_NOT_INSTALLABLE;
2747   static const int SOLVER_RULE_PKG_NOTHING_PROVIDES_DEP = SOLVER_RULE_PKG_NOTHING_PROVIDES_DEP;
2748   static const int SOLVER_RULE_PKG_REQUIRES = SOLVER_RULE_PKG_REQUIRES;
2749   static const int SOLVER_RULE_PKG_SELF_CONFLICT = SOLVER_RULE_PKG_SELF_CONFLICT;
2750   static const int SOLVER_RULE_PKG_CONFLICTS = SOLVER_RULE_PKG_CONFLICTS;
2751   static const int SOLVER_RULE_PKG_SAME_NAME = SOLVER_RULE_PKG_SAME_NAME;
2752   static const int SOLVER_RULE_PKG_OBSOLETES = SOLVER_RULE_PKG_OBSOLETES;
2753   static const int SOLVER_RULE_PKG_IMPLICIT_OBSOLETES = SOLVER_RULE_PKG_IMPLICIT_OBSOLETES;
2754   static const int SOLVER_RULE_PKG_INSTALLED_OBSOLETES = SOLVER_RULE_PKG_INSTALLED_OBSOLETES;
2755   static const int SOLVER_RULE_UPDATE = SOLVER_RULE_UPDATE;
2756   static const int SOLVER_RULE_FEATURE = SOLVER_RULE_FEATURE;
2757   static const int SOLVER_RULE_JOB = SOLVER_RULE_JOB;
2758   static const int SOLVER_RULE_JOB_NOTHING_PROVIDES_DEP = SOLVER_RULE_JOB_NOTHING_PROVIDES_DEP;
2759   static const int SOLVER_RULE_JOB_PROVIDED_BY_SYSTEM = SOLVER_RULE_JOB_PROVIDED_BY_SYSTEM;
2760   static const int SOLVER_RULE_JOB_UNKNOWN_PACKAGE = SOLVER_RULE_JOB_UNKNOWN_PACKAGE;
2761   static const int SOLVER_RULE_JOB_UNSUPPORTED = SOLVER_RULE_JOB_UNSUPPORTED;
2762   static const int SOLVER_RULE_DISTUPGRADE = SOLVER_RULE_DISTUPGRADE;
2763   static const int SOLVER_RULE_INFARCH = SOLVER_RULE_INFARCH;
2764   static const int SOLVER_RULE_CHOICE = SOLVER_RULE_CHOICE;
2765   static const int SOLVER_RULE_LEARNT = SOLVER_RULE_LEARNT;
2766
2767   static const int SOLVER_SOLUTION_JOB = SOLVER_SOLUTION_JOB;
2768   static const int SOLVER_SOLUTION_POOLJOB = SOLVER_SOLUTION_POOLJOB;
2769   static const int SOLVER_SOLUTION_INFARCH = SOLVER_SOLUTION_INFARCH;
2770   static const int SOLVER_SOLUTION_DISTUPGRADE = SOLVER_SOLUTION_DISTUPGRADE;
2771   static const int SOLVER_SOLUTION_BEST = SOLVER_SOLUTION_BEST;
2772   static const int SOLVER_SOLUTION_ERASE = SOLVER_SOLUTION_ERASE;
2773   static const int SOLVER_SOLUTION_REPLACE = SOLVER_SOLUTION_REPLACE;
2774   static const int SOLVER_SOLUTION_REPLACE_DOWNGRADE = SOLVER_SOLUTION_REPLACE_DOWNGRADE;
2775   static const int SOLVER_SOLUTION_REPLACE_ARCHCHANGE = SOLVER_SOLUTION_REPLACE_ARCHCHANGE;
2776   static const int SOLVER_SOLUTION_REPLACE_VENDORCHANGE = SOLVER_SOLUTION_REPLACE_VENDORCHANGE;
2777   static const int SOLVER_SOLUTION_REPLACE_NAMECHANGE = SOLVER_SOLUTION_REPLACE_NAMECHANGE;
2778
2779   static const int POLICY_ILLEGAL_DOWNGRADE = POLICY_ILLEGAL_DOWNGRADE;
2780   static const int POLICY_ILLEGAL_ARCHCHANGE = POLICY_ILLEGAL_ARCHCHANGE;
2781   static const int POLICY_ILLEGAL_VENDORCHANGE = POLICY_ILLEGAL_VENDORCHANGE;
2782   static const int POLICY_ILLEGAL_NAMECHANGE = POLICY_ILLEGAL_NAMECHANGE;
2783
2784   static const int SOLVER_FLAG_ALLOW_DOWNGRADE = SOLVER_FLAG_ALLOW_DOWNGRADE;
2785   static const int SOLVER_FLAG_ALLOW_ARCHCHANGE = SOLVER_FLAG_ALLOW_ARCHCHANGE;
2786   static const int SOLVER_FLAG_ALLOW_VENDORCHANGE = SOLVER_FLAG_ALLOW_VENDORCHANGE;
2787   static const int SOLVER_FLAG_ALLOW_NAMECHANGE = SOLVER_FLAG_ALLOW_NAMECHANGE;
2788   static const int SOLVER_FLAG_ALLOW_UNINSTALL = SOLVER_FLAG_ALLOW_UNINSTALL;
2789   static const int SOLVER_FLAG_NO_UPDATEPROVIDE = SOLVER_FLAG_NO_UPDATEPROVIDE;
2790   static const int SOLVER_FLAG_SPLITPROVIDES = SOLVER_FLAG_SPLITPROVIDES;
2791   static const int SOLVER_FLAG_IGNORE_RECOMMENDED = SOLVER_FLAG_IGNORE_RECOMMENDED;
2792   static const int SOLVER_FLAG_ADD_ALREADY_RECOMMENDED = SOLVER_FLAG_ADD_ALREADY_RECOMMENDED;
2793   static const int SOLVER_FLAG_NO_INFARCHCHECK = SOLVER_FLAG_NO_INFARCHCHECK;
2794   static const int SOLVER_FLAG_BEST_OBEY_POLICY = SOLVER_FLAG_BEST_OBEY_POLICY;
2795   static const int SOLVER_FLAG_NO_AUTOTARGET = SOLVER_FLAG_NO_AUTOTARGET;
2796   static const int SOLVER_FLAG_DUP_ALLOW_DOWNGRADE = SOLVER_FLAG_DUP_ALLOW_DOWNGRADE;
2797   static const int SOLVER_FLAG_DUP_ALLOW_ARCHCHANGE = SOLVER_FLAG_DUP_ALLOW_ARCHCHANGE;
2798   static const int SOLVER_FLAG_DUP_ALLOW_VENDORCHANGE = SOLVER_FLAG_DUP_ALLOW_VENDORCHANGE;
2799   static const int SOLVER_FLAG_DUP_ALLOW_NAMECHANGE = SOLVER_FLAG_DUP_ALLOW_NAMECHANGE;
2800   static const int SOLVER_FLAG_KEEP_ORPHANS = SOLVER_FLAG_KEEP_ORPHANS;
2801   static const int SOLVER_FLAG_BREAK_ORPHANS = SOLVER_FLAG_BREAK_ORPHANS;
2802   static const int SOLVER_FLAG_FOCUS_INSTALLED = SOLVER_FLAG_FOCUS_INSTALLED;
2803   static const int SOLVER_FLAG_YUM_OBSOLETES = SOLVER_FLAG_YUM_OBSOLETES;
2804   static const int SOLVER_FLAG_NEED_UPDATEPROVIDE = SOLVER_FLAG_NEED_UPDATEPROVIDE;
2805
2806   static const int SOLVER_REASON_UNRELATED = SOLVER_REASON_UNRELATED;
2807   static const int SOLVER_REASON_UNIT_RULE = SOLVER_REASON_UNIT_RULE;
2808   static const int SOLVER_REASON_KEEP_INSTALLED = SOLVER_REASON_KEEP_INSTALLED;
2809   static const int SOLVER_REASON_RESOLVE_JOB = SOLVER_REASON_RESOLVE_JOB;
2810   static const int SOLVER_REASON_UPDATE_INSTALLED = SOLVER_REASON_UPDATE_INSTALLED;
2811   static const int SOLVER_REASON_CLEANDEPS_ERASE = SOLVER_REASON_CLEANDEPS_ERASE;
2812   static const int SOLVER_REASON_RESOLVE = SOLVER_REASON_RESOLVE;
2813   static const int SOLVER_REASON_WEAKDEP = SOLVER_REASON_WEAKDEP;
2814   static const int SOLVER_REASON_RESOLVE_ORPHAN = SOLVER_REASON_RESOLVE_ORPHAN;
2815   static const int SOLVER_REASON_RECOMMENDED = SOLVER_REASON_RECOMMENDED;
2816   static const int SOLVER_REASON_SUPPLEMENTED = SOLVER_REASON_SUPPLEMENTED;
2817
2818   /* legacy */
2819   static const int SOLVER_RULE_RPM = SOLVER_RULE_RPM;
2820
2821   ~Solver() {
2822     solver_free($self);
2823   }
2824
2825   int set_flag(int flag, int value) {
2826     return solver_set_flag($self, flag, value);
2827   }
2828   int get_flag(int flag) {
2829     return solver_get_flag($self, flag);
2830   }
2831 #if defined(SWIGPYTHON)
2832   %pythoncode {
2833     def solve(self, jobs):
2834       j = []
2835       for job in jobs: j += [job.how, job.what]
2836       return self.solve_helper(j)
2837   }
2838 #endif
2839 #if defined(SWIGPERL)
2840   %perlcode {
2841     sub solv::Solver::solve {
2842       my ($self, $jobs) = @_;
2843       my @j = map {($_->{'how'}, $_->{'what'})} @$jobs;
2844       return $self->solve_helper(\@j);
2845     }
2846   }
2847 #endif
2848 #if defined(SWIGRUBY)
2849 %init %{
2850 rb_eval_string(
2851     "class Solv::Solver\n"
2852     "  def solve(jobs)\n"
2853     "    jl = []\n"
2854     "    jobs.each do |j| ; jl << j.how << j.what ; end\n"
2855     "    solve_helper(jl)\n"
2856     "  end\n"
2857     "end\n"
2858   );
2859 %}
2860 #endif
2861   %typemap(out) Queue solve_helper Queue2Array(Problem *, 1, new_Problem(arg1, id));
2862   %newobject solve_helper;
2863   Queue solve_helper(Queue jobs) {
2864     Queue q;
2865     int i, cnt;
2866     queue_init(&q);
2867     solver_solve($self, &jobs);
2868     cnt = solver_problem_count($self);
2869     for (i = 1; i <= cnt; i++)
2870       queue_push(&q, i);
2871     return q;
2872   }
2873   %newobject transaction;
2874   Transaction *transaction() {
2875     return solver_create_transaction($self);
2876   }
2877
2878   int describe_decision(XSolvable *s, XRule **OUTPUT) {
2879     int ruleid;
2880     int reason = solver_describe_decision($self, s->id, &ruleid);
2881     *OUTPUT = new_XRule($self, ruleid);
2882     return reason;
2883   }
2884
2885   int alternatives_count() {
2886     return solver_alternatives_count($self);
2887   }
2888
2889   %newobject alternative;
2890   Alternative *alternative(Id aid) {
2891     Alternative *a = solv_calloc(1, sizeof(*a));
2892     a->solv = $self;
2893     queue_init(&a->choices);
2894     a->type = solver_get_alternative($self, aid, &a->dep_id, &a->from_id, &a->chosen_id, &a->choices, &a->level);
2895     if (!a->type) {
2896       queue_free(&a->choices);
2897       solv_free(a);
2898       return 0;
2899     }
2900     if (a->type == SOLVER_ALTERNATIVE_TYPE_RULE) {
2901       a->rid = a->dep_id;
2902       a->dep_id = 0;
2903     }
2904     return a;
2905   }
2906
2907   %typemap(out) Queue all_alternatives Queue2Array(Alternative *, 1, Solver_alternative(arg1, id));
2908   %newobject all_alternatives;
2909   Queue all_alternatives() {
2910     Queue q;
2911     int i, cnt;
2912     queue_init(&q);
2913     cnt = solver_alternatives_count($self);
2914     for (i = 1; i <= cnt; i++)
2915       queue_push(&q, i);
2916     return q;
2917   }
2918 }
2919
2920 %extend Transaction {
2921   static const int SOLVER_TRANSACTION_IGNORE = SOLVER_TRANSACTION_IGNORE;
2922   static const int SOLVER_TRANSACTION_ERASE = SOLVER_TRANSACTION_ERASE;
2923   static const int SOLVER_TRANSACTION_REINSTALLED = SOLVER_TRANSACTION_REINSTALLED;
2924   static const int SOLVER_TRANSACTION_DOWNGRADED = SOLVER_TRANSACTION_DOWNGRADED;
2925   static const int SOLVER_TRANSACTION_CHANGED = SOLVER_TRANSACTION_CHANGED;
2926   static const int SOLVER_TRANSACTION_UPGRADED = SOLVER_TRANSACTION_UPGRADED;
2927   static const int SOLVER_TRANSACTION_OBSOLETED = SOLVER_TRANSACTION_OBSOLETED;
2928   static const int SOLVER_TRANSACTION_INSTALL = SOLVER_TRANSACTION_INSTALL;
2929   static const int SOLVER_TRANSACTION_REINSTALL = SOLVER_TRANSACTION_REINSTALL;
2930   static const int SOLVER_TRANSACTION_DOWNGRADE = SOLVER_TRANSACTION_DOWNGRADE;
2931   static const int SOLVER_TRANSACTION_CHANGE = SOLVER_TRANSACTION_CHANGE;
2932   static const int SOLVER_TRANSACTION_UPGRADE = SOLVER_TRANSACTION_UPGRADE;
2933   static const int SOLVER_TRANSACTION_OBSOLETES = SOLVER_TRANSACTION_OBSOLETES;
2934   static const int SOLVER_TRANSACTION_MULTIINSTALL = SOLVER_TRANSACTION_MULTIINSTALL;
2935   static const int SOLVER_TRANSACTION_MULTIREINSTALL = SOLVER_TRANSACTION_MULTIREINSTALL;
2936   static const int SOLVER_TRANSACTION_MAXTYPE = SOLVER_TRANSACTION_MAXTYPE;
2937   static const int SOLVER_TRANSACTION_SHOW_ACTIVE = SOLVER_TRANSACTION_SHOW_ACTIVE;
2938   static const int SOLVER_TRANSACTION_SHOW_ALL = SOLVER_TRANSACTION_SHOW_ALL;
2939   static const int SOLVER_TRANSACTION_SHOW_OBSOLETES = SOLVER_TRANSACTION_SHOW_OBSOLETES;
2940   static const int SOLVER_TRANSACTION_SHOW_MULTIINSTALL = SOLVER_TRANSACTION_SHOW_MULTIINSTALL;
2941   static const int SOLVER_TRANSACTION_CHANGE_IS_REINSTALL = SOLVER_TRANSACTION_CHANGE_IS_REINSTALL;
2942   static const int SOLVER_TRANSACTION_OBSOLETE_IS_UPGRADE = SOLVER_TRANSACTION_OBSOLETE_IS_UPGRADE;
2943   static const int SOLVER_TRANSACTION_MERGE_VENDORCHANGES = SOLVER_TRANSACTION_MERGE_VENDORCHANGES;
2944   static const int SOLVER_TRANSACTION_MERGE_ARCHCHANGES = SOLVER_TRANSACTION_MERGE_ARCHCHANGES;
2945   static const int SOLVER_TRANSACTION_RPM_ONLY = SOLVER_TRANSACTION_RPM_ONLY;
2946   static const int SOLVER_TRANSACTION_ARCHCHANGE = SOLVER_TRANSACTION_ARCHCHANGE;
2947   static const int SOLVER_TRANSACTION_VENDORCHANGE = SOLVER_TRANSACTION_VENDORCHANGE;
2948   static const int SOLVER_TRANSACTION_KEEP_ORDERDATA = SOLVER_TRANSACTION_KEEP_ORDERDATA;
2949   ~Transaction() {
2950     transaction_free($self);
2951   }
2952 #ifdef SWIGRUBY
2953   %rename("isempty?") isempty;
2954 #endif
2955   bool isempty() {
2956     return $self->steps.count == 0;
2957   }
2958
2959   %newobject othersolvable;
2960   XSolvable *othersolvable(XSolvable *s) {
2961     Id op = transaction_obs_pkg($self, s->id);
2962     return new_XSolvable($self->pool, op);
2963   }
2964
2965   %typemap(out) Queue allothersolvables Queue2Array(XSolvable *, 1, new_XSolvable(arg1->pool, id));
2966   %newobject allothersolvables;
2967   Queue allothersolvables(XSolvable *s) {
2968     Queue q;
2969     queue_init(&q);
2970     transaction_all_obs_pkgs($self, s->id, &q);
2971     return q;
2972   }
2973
2974   %typemap(out) Queue classify Queue2Array(TransactionClass *, 4, new_TransactionClass(arg1, arg2, id, idp[1], idp[2], idp[3]));
2975   %newobject classify;
2976   Queue classify(int mode = 0) {
2977     Queue q;
2978     queue_init(&q);
2979     transaction_classify($self, mode, &q);
2980     return q;
2981   }
2982
2983   /* deprecated, use newsolvables instead */
2984   %typemap(out) Queue newpackages Queue2Array(XSolvable *, 1, new_XSolvable(arg1->pool, id));
2985   %newobject newpackages;
2986   Queue newpackages() {
2987     Queue q;
2988     int cut;
2989     queue_init(&q);
2990     cut = transaction_installedresult(self, &q);
2991     queue_truncate(&q, cut);
2992     return q;
2993   }
2994
2995   /* deprecated, use keptsolvables instead */
2996   %typemap(out) Queue keptpackages Queue2Array(XSolvable *, 1, new_XSolvable(arg1->pool, id));
2997   %newobject keptpackages;
2998   Queue keptpackages() {
2999     Queue q;
3000     int cut;
3001     queue_init(&q);
3002     cut = transaction_installedresult(self, &q);
3003     if (cut)
3004       queue_deleten(&q, 0, cut);
3005     return q;
3006   }
3007
3008   %typemap(out) Queue newsolvables Queue2Array(XSolvable *, 1, new_XSolvable(arg1->pool, id));
3009   %newobject newsolvables;
3010   Queue newsolvables() {
3011     Queue q;
3012     int cut;
3013     queue_init(&q);
3014     cut = transaction_installedresult(self, &q);
3015     queue_truncate(&q, cut);
3016     return q;
3017   }
3018
3019   %typemap(out) Queue keptsolvables Queue2Array(XSolvable *, 1, new_XSolvable(arg1->pool, id));
3020   %newobject keptsolvables;
3021   Queue keptsolvables() {
3022     Queue q;
3023     int cut;
3024     queue_init(&q);
3025     cut = transaction_installedresult(self, &q);
3026     if (cut)
3027       queue_deleten(&q, 0, cut);
3028     return q;
3029   }
3030
3031   %typemap(out) Queue steps Queue2Array(XSolvable *, 1, new_XSolvable(arg1->pool, id));
3032   %newobject steps;
3033   Queue steps() {
3034     Queue q;
3035     queue_init_clone(&q, &$self->steps);
3036     return q;
3037   }
3038
3039   int steptype(XSolvable *s, int mode) {
3040     return transaction_type($self, s->id, mode);
3041   }
3042   int calc_installsizechange() {
3043     return transaction_calc_installsizechange($self);
3044   }
3045   void order(int flags=0) {
3046     transaction_order($self, flags);
3047   }
3048 }
3049
3050 %extend TransactionClass {
3051   TransactionClass(Transaction *trans, int mode, Id type, int count, Id fromid, Id toid) {
3052     TransactionClass *cl = solv_calloc(1, sizeof(*cl));
3053     cl->transaction = trans;
3054     cl->mode = mode;
3055     cl->type = type;
3056     cl->count = count;
3057     cl->fromid = fromid;
3058     cl->toid = toid;
3059     return cl;
3060   }
3061   %typemap(out) Queue solvables Queue2Array(XSolvable *, 1, new_XSolvable(arg1->transaction->pool, id));
3062   %newobject solvables;
3063   Queue solvables() {
3064     Queue q;
3065     queue_init(&q);
3066     transaction_classify_pkgs($self->transaction, $self->mode, $self->type, $self->fromid, $self->toid, &q);
3067     return q;
3068   }
3069   const char * const fromstr;
3070   const char * const tostr;
3071   %{
3072     SWIGINTERN const char *TransactionClass_fromstr_get(TransactionClass *cl) {
3073       return pool_id2str(cl->transaction->pool, cl->fromid);
3074     }
3075     SWIGINTERN const char *TransactionClass_tostr_get(TransactionClass *cl) {
3076       return pool_id2str(cl->transaction->pool, cl->toid);
3077     }
3078   %}
3079 }
3080
3081 %extend XRule {
3082   XRule(Solver *solv, Id id) {
3083     if (!id)
3084       return 0;
3085     XRule *xr = solv_calloc(1, sizeof(*xr));
3086     xr->solv = solv;
3087     xr->id = id;
3088     return xr;
3089   }
3090   int const type;
3091   %{
3092     SWIGINTERN int XRule_type_get(XRule *xr) {
3093       return solver_ruleclass(xr->solv, xr->id);
3094     }
3095   %}
3096   %newobject info;
3097   Ruleinfo *info() {
3098     Id type, source, target, dep;
3099     type = solver_ruleinfo($self->solv, $self->id, &source, &target, &dep);
3100     return new_Ruleinfo($self, type, source, target, dep);
3101   }
3102   %typemap(out) Queue allinfos Queue2Array(Ruleinfo *, 4, new_Ruleinfo(arg1, id, idp[1], idp[2], idp[3]));
3103   %newobject allinfos;
3104   Queue allinfos() {
3105     Queue q;
3106     queue_init(&q);
3107     solver_allruleinfos($self->solv, $self->id, &q);
3108     return q;
3109   }
3110
3111   bool __eq__(XRule *xr) {
3112     return $self->solv == xr->solv && $self->id == xr->id;
3113   }
3114   bool __ne__(XRule *xr) {
3115     return !XRule___eq__($self, xr);
3116   }
3117   %newobject __repr__;
3118   const char *__repr__() {
3119     char buf[20];
3120     sprintf(buf, "<Rule #%d>", $self->id);
3121     return solv_strdup(buf);
3122   }
3123 }
3124
3125 %extend Ruleinfo {
3126   Ruleinfo(XRule *r, Id type, Id source, Id target, Id dep_id) {
3127     Ruleinfo *ri = solv_calloc(1, sizeof(*ri));
3128     ri->solv = r->solv;
3129     ri->rid = r->id;
3130     ri->type = type;
3131     ri->source = source;
3132     ri->target = target;
3133     ri->dep_id = dep_id;
3134     return ri;
3135   }
3136   %newobject solvable;
3137   XSolvable * const solvable;
3138   %newobject othersolvable;
3139   XSolvable * const othersolvable;
3140   %newobject dep;
3141   Dep * const dep;
3142   %{
3143     SWIGINTERN XSolvable *Ruleinfo_solvable_get(Ruleinfo *ri) {
3144       return new_XSolvable(ri->solv->pool, ri->source);
3145     }
3146     SWIGINTERN XSolvable *Ruleinfo_othersolvable_get(Ruleinfo *ri) {
3147       return new_XSolvable(ri->solv->pool, ri->target);
3148     }
3149     SWIGINTERN Dep *Ruleinfo_dep_get(Ruleinfo *ri) {
3150       return new_Dep(ri->solv->pool, ri->dep_id);
3151     }
3152   %}
3153   const char *problemstr() {
3154     return solver_problemruleinfo2str($self->solv, $self->type, $self->source, $self->target, $self->dep_id);
3155   }
3156 }
3157
3158 %extend XRepodata {
3159   XRepodata(Repo *repo, Id id) {
3160     XRepodata *xr = solv_calloc(1, sizeof(*xr));
3161     xr->repo = repo;
3162     xr->id = id;
3163     return xr;
3164   }
3165   Id new_handle() {
3166     return repodata_new_handle(repo_id2repodata($self->repo, $self->id));
3167   }
3168   void set_id(Id solvid, Id keyname, DepId id) {
3169     repodata_set_id(repo_id2repodata($self->repo, $self->id), solvid, keyname, id);
3170   }
3171   void set_str(Id solvid, Id keyname, const char *str) {
3172     repodata_set_str(repo_id2repodata($self->repo, $self->id), solvid, keyname, str);
3173   }
3174   void set_poolstr(Id solvid, Id keyname, const char *str) {
3175     repodata_set_poolstr(repo_id2repodata($self->repo, $self->id), solvid, keyname, str);
3176   }
3177   void add_idarray(Id solvid, Id keyname, DepId id) {
3178     repodata_add_idarray(repo_id2repodata($self->repo, $self->id), solvid, keyname, id);
3179   }
3180   void add_flexarray(Id solvid, Id keyname, Id handle) {
3181     repodata_add_flexarray(repo_id2repodata($self->repo, $self->id), solvid, keyname, handle);
3182   }
3183   void set_checksum(Id solvid, Id keyname, Chksum *chksum) {
3184     const unsigned char *buf = solv_chksum_get(chksum, 0);
3185     if (buf)
3186       repodata_set_bin_checksum(repo_id2repodata($self->repo, $self->id), solvid, keyname, solv_chksum_get_type(chksum), buf);
3187   }
3188   const char *lookup_str(Id solvid, Id keyname) {
3189     return repodata_lookup_str(repo_id2repodata($self->repo, $self->id), solvid, keyname);
3190   }
3191   Queue lookup_idarray(Id solvid, Id keyname) {
3192     Queue r;
3193     queue_init(&r);
3194     repodata_lookup_idarray(repo_id2repodata($self->repo, $self->id), solvid, keyname, &r);
3195     return r;
3196   }
3197   %newobject lookup_checksum;
3198   Chksum *lookup_checksum(Id solvid, Id keyname) {
3199     Id type = 0;
3200     const unsigned char *b = repodata_lookup_bin_checksum(repo_id2repodata($self->repo, $self->id), solvid, keyname, &type);
3201     return solv_chksum_create_from_bin(type, b);
3202   }
3203   void internalize() {
3204     repodata_internalize(repo_id2repodata($self->repo, $self->id));
3205   }
3206   void create_stubs() {
3207     Repodata *data = repo_id2repodata($self->repo, $self->id);
3208     data = repodata_create_stubs(data);
3209     $self->id = data->repodataid;
3210   }
3211   bool write(FILE *fp) {
3212     return repodata_write(repo_id2repodata($self->repo, $self->id), fp) == 0;
3213   }
3214   bool add_solv(FILE *fp, int flags = 0) {
3215     Repodata *data = repo_id2repodata($self->repo, $self->id);
3216     int r, oldstate = data->state;
3217     data->state = REPODATA_LOADING;
3218     r = repo_add_solv(data->repo, fp, flags | REPO_USE_LOADING);
3219     if (r || data->state == REPODATA_LOADING)
3220       data->state = oldstate;
3221     return r;
3222   }
3223   void extend_to_repo() {
3224     Repodata *data = repo_id2repodata($self->repo, $self->id);
3225     repodata_extend_block(data, data->repo->start, data->repo->end - data->repo->start);
3226   }
3227   bool __eq__(XRepodata *xr) {
3228     return $self->repo == xr->repo && $self->id == xr->id;
3229   }
3230   bool __ne__(XRepodata *xr) {
3231     return !XRepodata___eq__($self, xr);
3232   }
3233   %newobject __repr__;
3234   const char *__repr__() {
3235     char buf[20];
3236     sprintf(buf, "<Repodata #%d>", $self->id);
3237     return solv_strdup(buf);
3238   }
3239 }
3240
3241 #ifdef ENABLE_PUBKEY
3242 %extend Solvsig {
3243   Solvsig(FILE *fp) {
3244     return solvsig_create(fp);
3245   }
3246   ~Solvsig() {
3247     solvsig_free($self);
3248   }
3249   %newobject Chksum;
3250   Chksum *Chksum() {
3251     return $self->htype ? (Chksum *)solv_chksum_create($self->htype) : 0;
3252   }
3253 #ifdef ENABLE_PGPVRFY
3254   %newobject verify;
3255   XSolvable *verify(Repo *repo, Chksum *chksum) {
3256     Id p = solvsig_verify($self, repo, chksum);
3257     return new_XSolvable(repo->pool, p);
3258   }
3259 #endif
3260 }
3261 #endif
3262
3263 %extend Alternative {
3264   static const int SOLVER_ALTERNATIVE_TYPE_RULE = SOLVER_ALTERNATIVE_TYPE_RULE;
3265   static const int SOLVER_ALTERNATIVE_TYPE_RECOMMENDS = SOLVER_ALTERNATIVE_TYPE_RECOMMENDS;
3266   static const int SOLVER_ALTERNATIVE_TYPE_SUGGESTS = SOLVER_ALTERNATIVE_TYPE_SUGGESTS;
3267
3268   ~Alternative() {
3269     queue_free(&$self->choices);
3270     solv_free($self);
3271   }
3272   %newobject chosen;
3273   XSolvable * const chosen;
3274   %newobject rule;
3275   XRule * const rule;
3276   %newobject depsolvable;
3277   XSolvable * const depsolvable;
3278   %newobject dep;
3279   Dep * const dep;
3280   %{
3281     SWIGINTERN XSolvable *Alternative_chosen_get(Alternative *a) {
3282       return new_XSolvable(a->solv->pool, a->chosen_id);
3283     }
3284     SWIGINTERN XRule *Alternative_rule_get(Alternative *a) {
3285       return new_XRule(a->solv, a->rid);
3286     }
3287     SWIGINTERN XSolvable *Alternative_depsolvable_get(Alternative *a) {
3288       return new_XSolvable(a->solv->pool, a->from_id);
3289     }
3290     SWIGINTERN Dep *Alternative_dep_get(Alternative *a) {
3291       return new_Dep(a->solv->pool, a->dep_id);
3292     }
3293   %}
3294
3295   Queue choices_raw() {
3296     Queue r;
3297     queue_init_clone(&r, &$self->choices);
3298     return r;
3299   }
3300
3301   %typemap(out) Queue choices Queue2Array(XSolvable *, 1, new_XSolvable(arg1->solv->pool, id));
3302   Queue choices() {
3303     int i;
3304     Queue r;
3305     queue_init_clone(&r, &$self->choices);
3306     for (i = 0; i < r.count; i++)
3307       if (r.elements[i] < 0)
3308         r.elements[i] = -r.elements[i];
3309     return r;
3310   }
3311
3312 #if defined(SWIGPERL)
3313   %rename("str") __str__;
3314 #endif
3315   const char *__str__() {
3316     return solver_alternative2str($self->solv, $self->type, $self->type == SOLVER_ALTERNATIVE_TYPE_RULE ? $self->rid : $self->dep_id, $self->from_id);
3317   }
3318 }