- swig bug: can't overload __str__ in perl, causes memory corruption as it tries...
[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 #
8 ##if defined(SWIGRUBY)
9 #  %rename("to_s") string();
10 ##endif
11 ##if defined(SWIGPYTHON)
12 #  %rename("__str__") string();
13 ##endif
14 #
15
16 %module solv
17
18 #ifdef SWIGRUBY
19 %markfunc Pool "mark_Pool";
20 #endif
21
22 #if defined(SWIGPYTHON)
23 %typemap(in) Queue {
24   /* Check if is a list */
25   queue_init(&$1);
26   if (PyList_Check($input)) {
27     int size = PyList_Size($input);
28     int i = 0;
29     for (i = 0; i < size; i++) {
30       PyObject *o = PyList_GetItem($input,i);
31       int v;
32       int e = SWIG_AsVal_int(o, &v);
33       if (!SWIG_IsOK(e)) {
34         SWIG_exception_fail(SWIG_ArgError(e), "list must contain only integers");
35         queue_free(&$1);
36         return NULL;
37       }
38       queue_push(&$1, v);
39     }
40   } else {
41     PyErr_SetString(PyExc_TypeError,"not a list");
42     return NULL;
43   }
44 }
45
46 %typemap(out) Queue {
47   int i;
48   PyObject *o = PyList_New($1.count);
49   for (i = 0; i < $1.count; i++)
50     PyList_SetItem(o, i, SWIG_From_int($1.elements[i]));
51   queue_free(&$1);
52   $result = o;
53 }
54
55 %define Queue2Array(type, step, con) %{
56   int i;
57   int cnt = $1.count / step;
58   Id *idp = $1.elements;
59   PyObject *o = PyList_New(cnt);
60   for (i = 0; i < cnt; i++, idp += step)
61     {
62       Id id = *idp;
63 #define result resultx
64       type result = con;
65       $typemap(out, type)
66       PyList_SetItem(o, i, $result);
67 #undef result
68     }
69   queue_free(&$1);
70   $result = o;
71 %}
72
73 %enddef
74
75 #endif
76
77
78 #if defined(SWIGPERL)
79 %typemap(in) Queue {
80   AV *av;
81   int i, size;
82   queue_init(&$1);
83   if (!SvROK($input) || SvTYPE(SvRV($input)) != SVt_PVAV)
84     SWIG_croak("Argument $argnum is not an array reference.");
85   av = (AV*)SvRV($input);
86   size = av_len(av);
87   for (i = 0; i <= size; i++) {
88     SV **sv = av_fetch(av, i, 0);
89     int v;
90     int e = SWIG_AsVal_int(*sv, &v);
91     if (!SWIG_IsOK(e)) {
92       SWIG_croak("list must contain only integers");
93     }
94     queue_push(&$1, v);
95   }
96 }
97 # AV *o = newAV();
98 # av_push(o, SvREFCNT_inc(SWIG_From_int($1.elements[i])));
99 # $result = newRV_noinc((SV*)o); argvi++;
100 #
101 %typemap(out) Queue {
102   int i;
103   if (argvi + $1.count + 1>= items) {
104     EXTEND(sp, items - (argvi + $1.count + 1) + 1);
105   }
106   for (i = 0; i < $1.count; i++)
107     ST(argvi++) = SvREFCNT_inc(SWIG_From_int($1.elements[i]));
108   queue_free(&$1);
109   $result = 0;
110 }
111 %define Queue2Array(type, step, con) %{
112   int i;
113   int cnt = $1.count / step;
114   Id *idp = $1.elements;
115   if (argvi + cnt + 1 >= items) {
116     EXTEND(sp, items - (argvi + cnt + 1) + 1);
117   }
118   for (i = 0; i < cnt; i++, idp += step)
119     {
120       Id id = *idp;
121 #define result resultx
122       type result = con;
123       $typemap(out, type)
124       SvREFCNT_inc(ST(argvi - 1));
125 #undef result
126     }
127   queue_free(&$1);
128   $result = 0;
129 %}
130 %enddef
131
132 #endif
133
134 %typemap(arginit) Queue {
135   queue_init(&$1);
136 }
137 %typemap(freearg) Queue {
138   queue_free(&$1);
139 }
140
141 #if defined(SWIGRUBY)
142 %typemap(in) Queue {
143   int size, i;
144   VALUE *o;
145   queue_init(&$1);
146   size = RARRAY($input)->len;
147   i = 0;
148   o = RARRAY($input)->ptr;
149   for (i = 0; i < size; i++, o++) {
150     int v;
151     int e = SWIG_AsVal_int(*o, &v);
152     if (!SWIG_IsOK(e))
153       {
154         SWIG_Error(SWIG_RuntimeError, "list must contain only integers");
155         SWIG_fail;
156       }
157     queue_push(&$1, v);
158   }
159 }
160 %typemap(out) Queue {
161   int i;
162   VALUE o = rb_ary_new2($1.count);
163   for (i = 0; i < $1.count; i++)
164     rb_ary_store(o, i, SWIG_From_int($1.elements[i]));
165   queue_free(&$1);
166   $result = o;
167 }
168 %typemap(arginit) Queue {
169   queue_init(&$1);
170 }
171 %typemap(freearg) Queue {
172   queue_free(&$1);
173 }
174 %define Queue2Array(type, step, con) %{
175   int i;
176   int cnt = $1.count / step;
177   Id *idp = $1.elements;
178   VALUE o = rb_ary_new2(cnt);
179   for (i = 0; i < cnt; i++, idp += step)
180     {
181       Id id = *idp;
182 #define result resultx
183       type result = con;
184       $typemap(out, type)
185       rb_ary_store(o, i, $result);
186 #undef result
187     }
188   queue_free(&$1);
189   $result = o;
190 %}
191 %enddef
192 #endif
193
194
195
196
197 #if defined(SWIGPERL)
198
199 # work around a swig bug
200 %{
201 #undef SWIG_CALLXS
202 #ifdef PERL_OBJECT 
203 #  define SWIG_CALLXS(_name) TOPMARK=MARK-PL_stack_base;_name(cv,pPerl) 
204 #else 
205 #  ifndef MULTIPLICITY 
206 #    define SWIG_CALLXS(_name) TOPMARK=MARK-PL_stack_base;_name(cv) 
207 #  else 
208 #    define SWIG_CALLXS(_name) TOPMARK=MARK-PL_stack_base;_name(PERL_GET_THX, cv) 
209 #  endif 
210 #endif 
211 %}
212
213
214 %define perliter(class)
215   %perlcode {
216     sub class##::FETCH {
217       my $i = ${##class##::ITERATORS}{$_[0]};
218       if ($i) {
219         $_[1] == $i->[0] - 1 ? $i->[1] : undef;
220       } else {
221         $_[0]->__getitem__($_[1]);
222       }
223     }
224     sub class##::FETCHSIZE {
225       my $i = ${##class##::ITERATORS}{$_[0]};
226       if ($i) {
227         ($i->[1] = $_[0]->__next__()) ? ++$i->[0]  : 0;
228       } else {
229         $_[0]->__len__();
230       }
231     }
232   }
233 %enddef
234
235 %{
236
237 #define SWIG_PERL_ITERATOR      0x80
238
239 SWIGRUNTIMEINLINE SV *
240 SWIG_Perl_NewArrayObj(SWIG_MAYBE_PERL_OBJECT void *ptr, swig_type_info *t, int flags) {
241   SV *result = sv_newmortal();
242   if (ptr && (flags & (SWIG_SHADOW | SWIG_POINTER_OWN))) {
243     SV *self;
244     SV *obj=newSV(0);
245     AV *array=newAV();
246     HV *stash;
247     sv_setref_pv(obj, (char *) SWIG_Perl_TypeProxyName(t), ptr);
248     stash=SvSTASH(SvRV(obj));
249     if (flags & SWIG_POINTER_OWN) {
250       HV *hv;
251       GV *gv=*(GV**)hv_fetch(stash, "OWNER", 5, TRUE);
252       if (!isGV(gv))
253         gv_init(gv, stash, "OWNER", 5, FALSE);
254       hv=GvHVn(gv);
255       hv_store_ent(hv, obj, newSViv(1), 0);
256     }
257     if (flags & SWIG_PERL_ITERATOR) {
258       HV *hv;
259       GV *gv=*(GV**)hv_fetch(stash, "ITERATORS", 9, TRUE);
260       AV *av=newAV();
261       if (!isGV(gv))
262         gv_init(gv, stash, "ITERATORS", 9, FALSE);
263       hv=GvHVn(gv);
264       hv_store_ent(hv, obj, newRV_inc((SV *)av), 0);
265     }
266     sv_magic((SV *)array, (SV *)obj, 'P', Nullch, 0);
267     SvREFCNT_dec(obj);
268     self=newRV_noinc((SV *)array);
269     sv_setsv(result, self);
270     SvREFCNT_dec((SV *)self);
271     sv_bless(result, stash);
272   } else {
273     sv_setref_pv(result, (char *) SWIG_Perl_TypeProxyName(t), ptr);
274   }
275   return result;
276 }
277
278 %}
279
280 %typemap(out) Perlarray {
281   ST(argvi) = SWIG_Perl_NewArrayObj(SWIG_PERL_OBJECT_CALL SWIG_as_voidptr(result), $1_descriptor, $owner | $shadow); argvi++;
282 }
283 %typemap(out) Perliterator {
284   ST(argvi) = SWIG_Perl_NewArrayObj(SWIG_PERL_OBJECT_CALL SWIG_as_voidptr(result), $1_descriptor, $owner | $shadow | SWIG_PERL_ITERATOR); argvi++;
285 }
286
287 %typemap(out) Pool_solvable_iterator * = Perlarray;
288 %typemap(out) Pool_solvable_iterator * solvables_iter = Perliterator;
289 %typemap(out) Pool_repo_iterator * = Perlarray;
290 %typemap(out) Pool_repo_iterator * repos_iter = Perliterator;
291 %typemap(out) Repo_solvable_iterator * = Perlarray;
292 %typemap(out) Repo_solvable_iterator * solvables_iter = Perliterator;
293 %typemap(out) Dataiterator * = Perliterator;
294
295 #endif
296
297
298
299 #if defined(SWIGPYTHON)
300 typedef PyObject *AppObjectPtr;
301 %typemap(out) AppObjectPtr {
302   $result = $1;
303   Py_INCREF($result);
304 }
305 #endif
306 #if defined(SWIGPERL)
307 typedef SV *AppObjectPtr;
308 %typemap(in) AppObjectPtr {
309   $1 = SvROK($input) ? SvRV($input) : 0;
310 }
311 %typemap(out) AppObjectPtr {
312   $result = $1 ? newRV_inc($1) : newSV(0);
313   argvi++;
314 }
315 #endif
316 #if defined(SWIGRUBY)
317 typedef VALUE AppObjectPtr;
318 %typemap(in) AppObjectPtr {
319   $1 = (void *)$input;
320 }
321 %typemap(out) AppObjectPtr {
322   $result = (VALUE)$1;
323 }
324 #endif
325
326
327 %include "cdata.i"
328 #ifndef SWIGPERL
329 %include "file.i"
330 #endif
331 %include "typemaps.i"
332
333 %{
334 #include <stdio.h>
335 #include <sys/stat.h>
336 #include <sys/types.h>
337 #include <unistd.h>
338
339 #include "pool.h"
340 #include "poolarch.h"
341 #include "solver.h"
342 #include "policy.h"
343 #include "solverdebug.h"
344 #include "repo_solv.h"
345 #include "chksum.h"
346
347 #ifndef DEBIAN
348 #include "repo_rpmdb.h"
349 #endif
350 #include "repo_deb.h"
351 #include "repo_rpmmd.h"
352 #include "repo_write.h"
353 #include "repo_products.h"
354 #include "repo_susetags.h"
355 #include "repo_updateinfoxml.h"
356 #include "repo_deltainfoxml.h"
357 #include "repo_repomdxml.h"
358 #include "repo_content.h"
359 #include "solv_xfopen.h"
360
361 #define true 1
362 #define false 1
363
364 #define SOLVER_SOLUTION_ERASE                   -100
365 #define SOLVER_SOLUTION_REPLACE                 -101
366 #define SOLVER_SOLUTION_REPLACE_DOWNGRADE       -102
367 #define SOLVER_SOLUTION_REPLACE_ARCHCHANGE      -103
368 #define SOLVER_SOLUTION_REPLACE_VENDORCHANGE    -104
369
370 typedef struct chksum Chksum;
371 typedef int bool;
372 typedef void *AppObjectPtr;
373
374 typedef struct {
375   Pool *pool;
376   Id id;
377 } Dep;
378
379 typedef struct {
380   Pool *pool;
381   Id id;
382 } XSolvable;
383
384 typedef struct {
385   Solver *solv;
386   Id id;
387 } XRule;
388
389 typedef struct {
390   Repo *repo;
391   Id id;
392 } XRepodata;
393
394 typedef struct {
395   Pool *pool;
396   Id id;
397 } Pool_solvable_iterator;
398
399 typedef struct {
400   Pool *pool;
401   Id id;
402 } Pool_repo_iterator;
403
404 typedef struct {
405   Repo *repo;
406   Id id;
407 } Repo_solvable_iterator;
408
409 typedef struct {
410   Pool *pool;
411   int how;
412   Id what;
413 } Job;
414
415 typedef struct {
416   Solver *solv;
417   Id id;
418 } Problem;
419
420 typedef struct {
421   Solver *solv;
422   Id problemid;
423   Id id;
424 } Solution;
425
426 typedef struct {
427   Solver *solv;
428   Id problemid;
429   Id solutionid;
430   Id id;
431
432   Id type;
433   Id p;
434   Id rp;
435 } Solutionelement;
436
437 typedef struct {
438   Solver *solv;
439   Id rid;
440   Id type;
441   Id source;
442   Id target;
443   Id dep;
444 } Ruleinfo;
445
446 typedef struct {
447   Transaction *transaction;
448   int mode;
449   Id type;
450   int count;
451   Id fromid;
452   Id toid;
453 } TransactionClass;
454
455 typedef Dataiterator Datamatch;
456
457 %}
458
459 #ifdef SWIGRUBY
460 %mixin Dataiterator "Enumerable";
461 %mixin Pool_solvable_iterator "Enumerable";
462 %mixin Pool_repo_iterator "Enumerable";
463 %mixin Repo_solvable_iterator "Enumerable";
464 #endif
465
466 typedef int Id;
467
468 %include "knownid.h"
469
470 # from repodata.h
471 %constant Id SOLVID_META;
472 %constant Id SOLVID_POS;
473
474 %constant int REL_EQ;
475 %constant int REL_GT;
476 %constant int REL_LT;
477 %constant int REL_ARCH;
478
479 typedef struct {
480   Pool* const pool;
481   Id const id;
482 } Dep;
483
484 typedef struct {
485   Pool* const pool;
486   Id const id;
487 } XSolvable;
488
489 typedef struct {
490   Solver* const solv;
491   Id const type;
492   Id const dep;
493 } Ruleinfo;
494
495 typedef struct {
496   Solver* const solv;
497   Id const id;
498 } XRule;
499
500 typedef struct {
501   Repo* const repo;
502   Id const id;
503 } XRepodata;
504
505 # put before pool/repo so we can access the constructor
506 %nodefaultdtor Dataiterator;
507 typedef struct {} Dataiterator;
508 typedef struct {} Pool_solvable_iterator;
509 typedef struct {} Pool_repo_iterator;
510 typedef struct {} Repo_solvable_iterator;
511
512 %nodefaultctor Datamatch;
513 %nodefaultdtor Datamatch;
514 typedef struct {
515   Pool * const pool;
516   Repo * const repo;
517   Id const solvid;
518 } Datamatch;
519
520 %nodefaultctor Datapos;
521 typedef struct {
522   Repo * const repo;
523 } Datapos;
524
525 typedef struct {
526   Pool * const pool;
527   int how;
528   Id what;
529 } Job;
530
531 %nodefaultctor Pool;
532 %nodefaultdtor Pool;
533 typedef struct {
534   AppObjectPtr appdata;
535 } Pool;
536
537 %nodefaultctor Repo;
538 %nodefaultdtor Repo;
539 typedef struct _Repo {
540   Pool * const pool;
541   const char * const name;
542   int priority;
543   int subpriority;
544   int const nsolvables;
545   AppObjectPtr appdata;
546 } Repo;
547
548 %nodefaultctor Solver;
549 %nodefaultdtor Solver;
550 typedef struct {
551   Pool * const pool;
552   bool fixsystem;
553   bool allowdowngrade;
554   bool allowarchchange;
555   bool allowvendorchange;
556   bool allowuninstall;
557   bool updatesystem;
558   bool noupdateprovide;
559   bool dosplitprovides;
560   bool dontinstallrecommended;
561   bool ignorealreadyrecommended;
562   bool dontshowinstalledrecommended;
563   bool distupgrade;
564   bool distupgrade_removeunsupported;
565   bool noinfarchcheck;
566 } Solver;
567
568 typedef struct chksum {
569 } Chksum;
570
571 %rename(xfopen) solv_xfopen;
572 %rename(xfopen_fd) solv_xfopen_fd;
573 %rename(xfopen_dup) solv_xfopen_dup;
574 %rename(xfclose) solv_xfclose;
575 %rename(xfileno) solv_xfileno;
576
577 FILE *solv_xfopen(const char *fn, const char *mode = 0);
578 FILE *solv_xfopen_fd(const char *fn, int fd, const char *mode = 0);
579 FILE *solv_xfopen_dup(const char *fn, int fd, const char *mode = 0);
580 int solv_xfclose(FILE *fp);
581 int solv_xfileno(FILE *fp);
582
583 %{
584   SWIGINTERN int solv_xfclose(FILE *fp) {
585     return fclose(fp);
586   }
587   SWIGINTERN int solv_xfileno(FILE *fp) {
588     return fileno(fp);
589   }
590   SWIGINTERN FILE *solv_xfopen_dup(const char *fn, int fd, const char *mode) {
591     fd = dup(fd);
592     return fd == -1 ? 0 : solv_xfopen_fd(fn, fd, mode);
593   }
594 %}
595
596 typedef struct {
597   Solver * const solv;
598   Id const id;
599 } Problem;
600
601 typedef struct {
602   Solver * const solv;
603   Id const problemid;
604   Id const id;
605 } Solution;
606
607 typedef struct {
608   Solver *const solv;
609   Id const problemid;
610   Id const solutionid;
611   Id const id;
612   Id const type;
613 } Solutionelement;
614
615 %nodefaultctor Transaction;
616 %nodefaultdtor Transaction;
617 typedef struct {
618   Pool * const pool;
619 } Transaction;
620
621 typedef struct {
622   Transaction * const transaction;
623   Id const type;
624   Id const fromid;
625   Id const toid;
626   int const count;
627 } TransactionClass;
628
629
630 %extend Job {
631   static const Id SOLVER_SOLVABLE = SOLVER_SOLVABLE;
632   static const Id SOLVER_SOLVABLE_NAME = SOLVER_SOLVABLE_NAME;
633   static const Id SOLVER_SOLVABLE_PROVIDES = SOLVER_SOLVABLE_PROVIDES;
634   static const Id SOLVER_SOLVABLE_ONE_OF = SOLVER_SOLVABLE_ONE_OF;
635   static const Id SOLVER_SOLVABLE_REPO = SOLVER_SOLVABLE_REPO;
636   static const Id SOLVER_SOLVABLE_ALL = SOLVER_SOLVABLE_ALL;
637   static const Id SOLVER_SELECTMASK = SOLVER_SELECTMASK;
638   static const Id SOLVER_NOOP = SOLVER_NOOP;
639   static const Id SOLVER_INSTALL = SOLVER_INSTALL;
640   static const Id SOLVER_ERASE = SOLVER_ERASE;
641   static const Id SOLVER_UPDATE = SOLVER_UPDATE;
642   static const Id SOLVER_WEAKENDEPS = SOLVER_WEAKENDEPS;
643   static const Id SOLVER_NOOBSOLETES = SOLVER_NOOBSOLETES;
644   static const Id SOLVER_LOCK = SOLVER_LOCK;
645   static const Id SOLVER_DISTUPGRADE = SOLVER_DISTUPGRADE;
646   static const Id SOLVER_VERIFY = SOLVER_VERIFY;
647   static const Id SOLVER_DROP_ORPHANED = SOLVER_DROP_ORPHANED;
648   static const Id SOLVER_USERINSTALLED = SOLVER_USERINSTALLED;
649   static const Id SOLVER_JOBMASK = SOLVER_JOBMASK;
650   static const Id SOLVER_WEAK = SOLVER_WEAK;
651   static const Id SOLVER_ESSENTIAL = SOLVER_ESSENTIAL;
652   static const Id SOLVER_CLEANDEPS = SOLVER_CLEANDEPS;
653   static const Id SOLVER_SETEV = SOLVER_SETEV;
654   static const Id SOLVER_SETEVR = SOLVER_SETEVR;
655   static const Id SOLVER_SETARCH = SOLVER_SETARCH;
656   static const Id SOLVER_SETVENDOR = SOLVER_SETVENDOR;
657   static const Id SOLVER_SETREPO = SOLVER_SETREPO;
658   static const Id SOLVER_NOAUTOSET = SOLVER_NOAUTOSET;
659   static const Id SOLVER_SETMASK = SOLVER_SETMASK;
660
661   Job(Pool *pool, int how, Id what) {
662     Job *job = solv_calloc(1, sizeof(*job));
663     job->pool = pool;
664     job->how = how;
665     job->what = what;
666     return job;
667   }
668
669   %typemap(out) Queue solvables Queue2Array(XSolvable *, 1, new_XSolvable(arg1->pool, id));
670   %newobject solvables;
671   Queue solvables() {
672     Pool *pool = $self->pool;
673     Id p, pp, how;
674     Queue q;
675     queue_init(&q);
676     how = $self->how & SOLVER_SELECTMASK;
677     FOR_JOB_SELECT(p, pp, how, $self->what)
678       queue_push(&q, p);
679     return q;
680   }
681
682   bool __eq__(Job *j) {
683     return $self->pool == j->pool && $self->how == j->how && $self->what == j->what;
684   }
685   bool __ne__(Job *j) {
686     return !Job___eq__($self, j);
687   }
688 #if defined(SWIGPERL)
689   %rename("str") __str__;
690 #endif
691   const char *__str__() {
692     return pool_job2str($self->pool, $self->how, $self->what, 0);
693   }
694   const char *__repr__() {
695     const char *str = pool_job2str($self->pool, $self->how, $self->what, ~0);
696     return pool_tmpjoin($self->pool, "<Job ", str, ">");
697   }
698 }
699
700 %extend Chksum {
701   Chksum(Id type) {
702     return (Chksum *)solv_chksum_create(type);
703   }
704   Chksum(Id type, const char *hex) {
705     unsigned char buf[64];
706     int l = solv_chksum_len(type);
707     if (!l)
708       return 0;
709     if (solv_hex2bin(&hex, buf, sizeof(buf)) != l || hex[0])
710       return 0;
711     return (Chksum *)solv_chksum_create_from_bin(type, buf);
712   }
713   ~Chksum() {
714     solv_chksum_free($self, 0);
715   }
716   Id const type;
717   %{
718   SWIGINTERN Id Chksum_type_get(Chksum *chksum) {
719     return solv_chksum_get_type(chksum);
720   }
721   %}
722   void add(const char *str) {
723     solv_chksum_add($self, str, strlen((char *)str));
724   }
725   void add_fp(FILE *fp) {
726     char buf[4096];
727     int l;
728     while ((l = fread(buf, 1, sizeof(buf), fp)) > 0)
729       solv_chksum_add($self, buf, l);
730     rewind(fp);         /* convenience */
731   }
732   void add_fd(int fd) {
733     char buf[4096];
734     int l;
735     while ((l = read(fd, buf, sizeof(buf))) > 0)
736       solv_chksum_add($self, buf, l);
737     lseek(fd, 0, 0);    /* convenience */
738   }
739   void add_stat(const char *filename) {
740     struct stat stb;
741     if (stat(filename, &stb))
742       memset(&stb, 0, sizeof(stb));
743     solv_chksum_add($self, &stb.st_dev, sizeof(stb.st_dev));
744     solv_chksum_add($self, &stb.st_ino, sizeof(stb.st_ino));
745     solv_chksum_add($self, &stb.st_size, sizeof(stb.st_size));
746     solv_chksum_add($self, &stb.st_mtime, sizeof(stb.st_mtime));
747   }
748   SWIGCDATA raw() {
749     int l;
750     const unsigned char *b;
751     b = solv_chksum_get($self, &l);
752     return cdata_void((void *)b, l);
753   }
754   %newobject hex;
755   char *hex() {
756     int l;
757     const unsigned char *b;
758     char *ret;
759
760     b = solv_chksum_get($self, &l);
761     ret = solv_malloc(2 * l + 1);
762     solv_bin2hex(b, l, ret);
763     return ret;
764   }
765
766   bool __eq__(Chksum *chk) {
767     int l;
768     const unsigned char *b, *bo;
769     if (!chk)
770       return 0;
771     if (solv_chksum_get_type($self) != solv_chksum_get_type(chk))
772       return 0;
773     b = solv_chksum_get($self, &l);
774     bo = solv_chksum_get(chk, 0);
775     return memcmp(b, bo, l) == 0;
776   }
777   bool __ne__(Chksum *chk) {
778     return !Chksum___eq__($self, chk);
779   }
780 #if defined(SWIGRUBY)
781   %rename("to_s") __str__;
782   %rename("inspect") __repr__;
783 #endif
784 #if defined(SWIGPERL)
785   %rename("str") __str__;
786 #endif
787   %newobject __str__;
788   const char *__str__() {
789     const char *str;
790     const char *h = 0;
791     if (solv_chksum_isfinished($self))
792       h = Chksum_hex($self);
793     str = solv_dupjoin(solv_chksum_type2str(solv_chksum_get_type($self)), ":", h ? h : "unfinished");
794     solv_free((void *)h);
795     return str;
796   }
797   %newobject __repr__;
798   const char *__repr__() {
799     const char *h = Chksum___str__($self);
800     const char *str = solv_dupjoin("<Chksum ", h, ">");
801     solv_free((void *)h);
802     return str;
803   }
804 }
805
806 %extend Pool {
807   Pool() {
808     Pool *pool = pool_create();
809     return pool;
810   }
811   ~Pool() {
812   }
813   void set_debuglevel(int level) {
814     pool_setdebuglevel($self, level);
815   }
816 #if defined(SWIGPYTHON)
817   %{
818   SWIGINTERN int loadcallback(Pool *pool, Repodata *data, void *d) {
819     XRepodata *xd = new_XRepodata(data->repo, data - data->repo->repodata);
820     PyObject *args = Py_BuildValue("(O)", SWIG_NewPointerObj(SWIG_as_voidptr(xd), SWIGTYPE_p_XRepodata, SWIG_POINTER_OWN | 0));
821     PyObject *result = PyEval_CallObject((PyObject *)d, args);
822     int ecode = 0;
823     int vresult = 0;
824     Py_DECREF(args);
825     if (!result)
826       return 0; /* exception */
827     ecode = SWIG_AsVal_int(result, &vresult);
828     Py_DECREF(result);
829     return SWIG_IsOK(ecode) ? vresult : 0;
830   }
831   %}
832   void set_loadcallback(PyObject *callable) {
833     if ($self->loadcallback == loadcallback)
834       Py_DECREF($self->loadcallbackdata);
835     if (callable)
836       Py_INCREF(callable);
837     pool_setloadcallback($self, callable ? loadcallback : 0, callable);
838   }
839 #endif
840 #if defined(SWIGPERL)
841 %{
842   SWIGINTERN int loadcallback(Pool *pool, Repodata *data, void *d) {
843     int count;
844     int ret = 0;
845     dSP;
846     XRepodata *xd = new_XRepodata(data->repo, data - data->repo->repodata);
847
848     ENTER;
849     SAVETMPS;
850     PUSHMARK(SP);
851     XPUSHs(SWIG_NewPointerObj(SWIG_as_voidptr(xd), SWIGTYPE_p_XRepodata, SWIG_OWNER | SWIG_SHADOW));
852     PUTBACK;
853     count = perl_call_sv((SV *)d, G_EVAL|G_SCALAR);
854     SPAGAIN;
855     if (count)
856       ret = POPi;
857     PUTBACK;
858     FREETMPS;
859     LEAVE;
860     return ret;
861   }
862 %}
863   void set_loadcallback(SV *callable) {
864     if ($self->loadcallback == loadcallback)
865       SvREFCNT_dec($self->loadcallbackdata);
866     if (callable)
867       SvREFCNT_inc(callable);
868     pool_setloadcallback($self, callable ? loadcallback : 0, callable);
869   }
870 #endif
871
872 #if defined(SWIGRUBY)
873 %{
874   SWIGINTERN int loadcallback(Pool *pool, Repodata *data, void *d) {
875     XRepodata *xd = new_XRepodata(data->repo, data - data->repo->repodata);
876     VALUE callable = (VALUE)d;
877     VALUE rd = SWIG_NewPointerObj(SWIG_as_voidptr(xd), SWIGTYPE_p_XRepodata, SWIG_POINTER_OWN | 0);
878     VALUE res = rb_funcall(callable, rb_intern("call"), 1, rd);
879     return res == Qtrue;
880   }
881   SWIGINTERN void mark_Pool(void *ptr) {
882     Pool *pool = ptr;
883     if (pool->loadcallback == loadcallback && pool->loadcallbackdata) {
884       VALUE callable = (VALUE)pool->loadcallbackdata;
885       rb_gc_mark(callable);
886     }
887   }
888 %}
889   %typemap(in, numinputs=0) VALUE callable {
890     $1 = rb_block_given_p() ? rb_block_proc() : 0;
891   }
892   void set_loadcallback(VALUE callable) {
893     pool_setloadcallback($self, callable ? loadcallback : 0, (void *)callable);
894   }
895 #endif
896
897   void free() {
898     Pool_set_loadcallback($self, 0);
899     pool_free($self);
900   }
901   Id str2id(const char *str, bool create=1) {
902     return pool_str2id($self, str, create);
903   }
904   const char *id2str(Id id) {
905     return pool_id2str($self, id);
906   }
907   const char *dep2str(Id id) {
908     return pool_dep2str($self, id);
909   }
910   Id rel2id(Id name, Id evr, int flags, bool create=1) {
911     return pool_rel2id($self, name, evr, flags, create);
912   }
913   Id id2langid(Id id, const char *lang, bool create=1) {
914     return pool_id2langid($self, id, lang, create);
915   }
916   void setarch(const char *arch) {
917     pool_setarch($self, arch);
918   }
919   Repo *add_repo(const char *name) {
920     return repo_create($self, name);
921   }
922   const char *lookup_str(Id entry, Id keyname) {
923     return pool_lookup_str($self, entry, keyname);
924   }
925   Id lookup_id(Id entry, Id keyname) {
926     return pool_lookup_id($self, entry, keyname);
927   }
928   unsigned int lookup_num(Id entry, Id keyname, unsigned int notfound = 0) {
929     return pool_lookup_num($self, entry, keyname, notfound);
930   }
931   bool lookup_void(Id entry, Id keyname) {
932     return pool_lookup_void($self, entry, keyname);
933   }
934   %newobject lookup_checksum;
935   Chksum *lookup_checksum(Id entry, Id keyname) {
936     Id type = 0;
937     const unsigned char *b = pool_lookup_bin_checksum($self, entry, keyname, &type);
938     return solv_chksum_create_from_bin(type, b);
939   }
940
941   %newobject Dataiterator;
942   Dataiterator *Dataiterator(Id p, Id key, const char *match, int flags) {
943     return new_Dataiterator($self, 0, p, key, match, flags);
944   }
945   const char *solvid2str(Id solvid) {
946     return pool_solvid2str($self, solvid);
947   }
948   void addfileprovides() {
949     pool_addfileprovides($self);
950   }
951   Queue addfileprovides_ids() {
952     Queue r;
953     Id *addedfileprovides = 0;
954     queue_init(&r);
955     pool_addfileprovides_ids($self, $self->installed, &addedfileprovides);
956     if (addedfileprovides) {
957       for (; *addedfileprovides; addedfileprovides++)
958         queue_push(&r, *addedfileprovides);
959     }
960     return r;
961   }
962   void createwhatprovides() {
963     pool_createwhatprovides($self);
964   }
965
966   XSolvable *id2solvable(Id id) {
967     return new_XSolvable($self, id);
968   }
969   %newobject solvables;
970   Pool_solvable_iterator * const solvables;
971   %{
972   SWIGINTERN Pool_solvable_iterator * Pool_solvables_get(Pool *pool) {
973     return new_Pool_solvable_iterator(pool);
974   }
975   %}
976   %newobject solvables_iter;
977   Pool_solvable_iterator * solvables_iter() {
978     return new_Pool_solvable_iterator($self);
979   }
980
981   Repo *id2repo(Id id) {
982     if (id < 1 || id > $self->nrepos)
983       return 0;
984     return pool_id2repo($self, id);
985   }
986   %newobject repos;
987   Pool_repo_iterator * const repos;
988   %{
989   SWIGINTERN Pool_repo_iterator * Pool_repos_get(Pool *pool) {
990     return new_Pool_repo_iterator(pool);
991   }
992   %}
993   %newobject repos_iter;
994   Pool_repo_iterator * repos_iter() {
995     return new_Pool_repo_iterator($self);
996   }
997
998   Repo *installed;
999   %{
1000   SWIGINTERN void Pool_installed_set(Pool *pool, Repo *installed) {
1001     pool_set_installed(pool, installed);
1002   }
1003   Repo *Pool_installed_get(Pool *pool) {
1004     return pool->installed;
1005   }
1006   %}
1007
1008   Queue matchprovidingids(const char *match, int flags) {
1009     Pool *pool = $self;
1010     Queue q;
1011     Id id;
1012     queue_init(&q);
1013     if (!flags) {
1014       for (id = 1; id < pool->ss.nstrings; id++)
1015         if (pool->whatprovides[id])
1016           queue_push(&q, id);
1017     } else {
1018       Datamatcher ma;
1019       if (!datamatcher_init(&ma, match, flags)) {
1020         for (id = 1; id < pool->ss.nstrings; id++)
1021           if (pool->whatprovides[id] && datamatcher_match(&ma, pool_id2str(pool, id)))
1022             queue_push(&q, id);
1023         datamatcher_free(&ma);
1024       }
1025     }
1026     return q;
1027   }
1028
1029   Job *Job(int how, Id what) {
1030     return new_Job($self, how, what);
1031   }
1032
1033   %typemap(out) Queue whatprovides Queue2Array(XSolvable *, 1, new_XSolvable(arg1, id));
1034   %newobject whatprovides;
1035   Queue whatprovides(Id dep) {
1036     Pool *pool = $self;
1037     Queue q;
1038     Id p, pp;
1039     queue_init(&q);
1040     FOR_PROVIDES(p, pp, dep)
1041       queue_push(&q, p);
1042     return q;
1043   }
1044
1045   Id towhatprovides(Queue q) {
1046     return pool_queuetowhatprovides($self, &q);
1047   }
1048
1049 #ifdef SWIGRUBY
1050   %rename("isknownarch?") isknownarch;
1051 #endif
1052   bool isknownarch(Id id) {
1053     Pool *pool = $self;
1054     if (!id || id == ID_EMPTY)
1055       return 0;
1056     if (id == ARCH_SRC || id == ARCH_NOSRC || id == ARCH_NOARCH)
1057       return 1;
1058     if (pool->id2arch && (id > pool->lastarch || !pool->id2arch[id]))
1059       return 0;
1060     return 1;
1061   }
1062
1063   %newobject Solver;
1064   Solver *Solver() {
1065     return solver_create($self);
1066   }
1067 }
1068
1069 %extend Repo {
1070   static const int REPO_REUSE_REPODATA = REPO_REUSE_REPODATA;
1071   static const int REPO_NO_INTERNALIZE = REPO_NO_INTERNALIZE;
1072   static const int REPO_LOCALPOOL = REPO_LOCALPOOL;
1073   static const int REPO_USE_LOADING = REPO_USE_LOADING;
1074   static const int REPO_EXTEND_SOLVABLES = REPO_EXTEND_SOLVABLES;
1075   static const int SOLV_ADD_NO_STUBS = SOLV_ADD_NO_STUBS;       /* repo_solv */
1076   static const int SUSETAGS_RECORD_SHARES = SUSETAGS_RECORD_SHARES; /* repo_susetags */
1077   static const int SOLV_ADD_NO_STUBS = SOLV_ADD_NO_STUBS ; /* repo_solv */
1078
1079   void free(bool reuseids = 0) {
1080     repo_free($self, reuseids);
1081   }
1082   void empty(bool reuseids = 0) {
1083     repo_empty($self, reuseids);
1084   }
1085 #ifdef SWIGRUBY
1086   %rename("isempty?") isempty;
1087 #endif
1088   bool isempty() {
1089     return !$self->nsolvables;
1090   }
1091   bool add_solv(const char *name, int flags = 0) {
1092     FILE *fp = fopen(name, "r");
1093     int r;
1094     if (!fp)
1095       return 0;
1096     r = repo_add_solv_flags($self, fp, flags);
1097     fclose(fp);
1098     return r == 0;
1099   }
1100   bool add_solv(FILE *fp, int flags = 0) {
1101     return repo_add_solv_flags($self, fp, flags) == 0;
1102   }
1103   bool add_products(const char *proddir, int flags = 0) {
1104     repo_add_products($self, proddir, 0, flags);
1105     return 1;
1106   }
1107   bool add_rpmmd(FILE *fp, const char *language, int flags = 0) {
1108     repo_add_rpmmd($self, fp, language, flags);
1109     return 1;
1110   }
1111 #ifndef DEBIAN
1112   bool add_rpmdb(Repo *ref, int flags = 0) {
1113     repo_add_rpmdb($self, ref, 0, flags);
1114     return 1;
1115   }
1116   Id add_rpm(const char *name, int flags = 0) {
1117     return repo_add_rpm($self, name, flags);
1118   }
1119 #endif
1120   bool add_debdb(int flags = 0) {
1121     repo_add_debdb($self, 0, flags);
1122     return 1;
1123   }
1124   Id add_deb(const char *name, int flags = 0) {
1125     return repo_add_deb($self, name, flags);
1126   }
1127   bool add_susetags(FILE *fp, Id defvendor, const char *language, int flags = 0) {
1128     repo_add_susetags($self, fp, defvendor, language, flags);
1129     return 1;
1130   }
1131   bool add_repomdxml(FILE *fp, int flags = 0) {
1132     repo_add_repomdxml($self, fp, flags);
1133     return 1;
1134   }
1135   bool add_content(FILE *fp, int flags = 0) {
1136     repo_add_content($self, fp, flags);
1137     return 1;
1138   }
1139   bool add_updateinfoxml(FILE *fp, int flags = 0) {
1140     repo_add_updateinfoxml($self, fp, flags);
1141     return 1;
1142   }
1143   bool add_deltainfoxml(FILE *fp, int flags = 0) {
1144     repo_add_deltainfoxml($self, fp, flags);
1145     return 1;
1146   }
1147   void internalize() {
1148     repo_internalize($self);
1149   }
1150   const char *lookup_str(Id entry, Id keyname) {
1151     return repo_lookup_str($self, entry, keyname);
1152   }
1153   Id lookup_id(Id entry, Id keyname) {
1154     return repo_lookup_id($self, entry, keyname);
1155   }
1156   unsigned int lookup_num(Id entry, Id keyname, unsigned int notfound = 0) {
1157     return repo_lookup_num($self, entry, keyname, notfound);
1158   }
1159   void write(FILE *fp) {
1160     repo_write($self, fp, repo_write_stdkeyfilter, 0, 0);
1161   }
1162   # HACK, remove if no longer needed!
1163   bool write_first_repodata(FILE *fp) {
1164     int oldnrepodata = $self->nrepodata;
1165     $self->nrepodata = 1;
1166     repo_write($self, fp, repo_write_stdkeyfilter, 0, 0);
1167     $self->nrepodata = oldnrepodata;
1168     return 1;
1169   }
1170
1171   %newobject Dataiterator;
1172   Dataiterator *Dataiterator(Id p, Id key, const char *match, int flags) {
1173     return new_Dataiterator($self->pool, $self, p, key, match, flags);
1174   }
1175
1176   Id const id;
1177   %{
1178   SWIGINTERN Id Repo_id_get(Repo *repo) {
1179     return repo->repoid;
1180   }
1181   %}
1182   Repo_solvable_iterator * const solvables;
1183   %{
1184   SWIGINTERN Repo_solvable_iterator * Repo_solvables_get(Repo *repo) {
1185     return new_Repo_solvable_iterator(repo);
1186   }
1187   %}
1188   %newobject solvables_iter;
1189   Repo_solvable_iterator *solvables_iter() {
1190     return new_Repo_solvable_iterator($self);
1191   }
1192
1193   XRepodata *add_repodata(int flags = 0) {
1194     Repodata *rd = repo_add_repodata($self, flags);
1195     return new_XRepodata($self, rd - $self->repodata);
1196   }
1197
1198   void create_stubs() {
1199     Repodata *data;
1200     if (!$self->nrepodata)
1201       return;
1202     data = $self->repodata  + ($self->nrepodata - 1);
1203     if (data->state != REPODATA_STUB)
1204       repodata_create_stubs(data);
1205   }
1206 #ifdef SWIGRUBY
1207   %rename("iscontiguous?") iscontiguous;
1208 #endif
1209   bool iscontiguous() {
1210     int i;
1211     for (i = $self->start; i < $self->end; i++)
1212       if ($self->pool->solvables[i].repo != $self)
1213         return 0;
1214     return 1;
1215   }
1216   XRepodata *first_repodata() {
1217      int i;
1218      if (!$self->nrepodata)
1219        return 0;
1220      /* make sure all repodatas but the first are extensions */
1221      if ($self->repodata[0].loadcallback)
1222         return 0;
1223      for (i = 1; i < $self->nrepodata; i++)
1224        if (!$self->repodata[i].loadcallback)
1225          return 0;       /* oops, not an extension */
1226      return new_XRepodata($self, 0);
1227    }
1228
1229   bool __eq__(Repo *repo) {
1230     return $self == repo;
1231   }
1232   bool __ne__(Repo *repo) {
1233     return $self != repo;
1234   }
1235 #if defined(SWIGPERL)
1236   %rename("str") __str__;
1237 #endif
1238   %newobject __str__;
1239   const char *__str__() {
1240     char buf[20];
1241     if ($self->name)
1242       return strdup($self->name);
1243     sprintf(buf, "Repo#%d", $self->repoid);
1244     return strdup(buf);
1245   }
1246   %newobject __repr__;
1247   const char *__repr__() {
1248     char buf[20];
1249     if ($self->name)
1250       {
1251         sprintf(buf, "<Repo #%d ", $self->repoid);
1252         return solv_dupjoin(buf, $self->name, ">");
1253       }
1254     sprintf(buf, "<Repo #%d>", $self->repoid);
1255     return strdup(buf);
1256   }
1257 }
1258
1259 %extend Dataiterator {
1260   static const int SEARCH_STRING = SEARCH_STRING;
1261   static const int SEARCH_SUBSTRING = SEARCH_SUBSTRING;
1262   static const int SEARCH_GLOB = SEARCH_GLOB;
1263   static const int SEARCH_REGEX = SEARCH_REGEX;
1264   static const int SEARCH_NOCASE = SEARCH_NOCASE;
1265   static const int SEARCH_FILES = SEARCH_FILES;
1266   static const int SEARCH_COMPLETE_FILELIST = SEARCH_COMPLETE_FILELIST;
1267
1268   Dataiterator(Pool *pool, Repo *repo, Id p, Id key, const char *match, int flags) {
1269     Dataiterator *di = solv_calloc(1, sizeof(*di));
1270     dataiterator_init(di, pool, repo, p, key, match, flags);
1271     return di;
1272   }
1273   ~Dataiterator() {
1274     dataiterator_free($self);
1275     solv_free($self);
1276   }
1277 #if defined(SWIGPYTHON)
1278   %newobject __iter__;
1279   Dataiterator *__iter__() {
1280     Dataiterator *ndi;
1281     ndi = solv_calloc(1, sizeof(*ndi));
1282     dataiterator_init_clone(ndi, $self);
1283     return ndi;
1284   }
1285   %rename("next") __next__();
1286   %exception __next__ {
1287     $action
1288     if (!result) {
1289       PyErr_SetString(PyExc_StopIteration,"no more matches");
1290       return NULL;
1291     }
1292   }
1293 #endif
1294
1295 #ifdef SWIGPERL
1296   perliter(solv::Dataiterator)
1297 #endif
1298
1299   %newobject __next__;
1300   Datamatch *__next__() {
1301     Dataiterator *ndi;
1302     if (!dataiterator_step($self)) {
1303       return 0;
1304     }
1305     ndi = solv_calloc(1, sizeof(*ndi));
1306     dataiterator_init_clone(ndi, $self);
1307     return ndi;
1308   }
1309 #ifdef SWIGRUBY
1310   void each() {
1311     Datamatch *d;
1312     while ((d = Dataiterator___next__($self)) != 0) {
1313       rb_yield(SWIG_NewPointerObj(SWIG_as_voidptr(d), SWIGTYPE_p_Datamatch, SWIG_POINTER_OWN | 0));
1314     }
1315   }
1316 #endif
1317   void prepend_keyname(Id key) {
1318     dataiterator_prepend_keyname($self, key);
1319   }
1320   void skip_solvable() {
1321     dataiterator_skip_solvable($self);
1322   }
1323 }
1324
1325 %extend Datamatch {
1326   ~Datamatch() {
1327     dataiterator_free($self);
1328     solv_free($self);
1329   }
1330   %newobject solvable;
1331   XSolvable * const solvable;
1332   %{
1333   SWIGINTERN XSolvable *Datamatch_solvable_get(Dataiterator *di) {
1334     return new_XSolvable(di->pool, di->solvid);
1335   }
1336   %}
1337   Id key_id() {
1338     return $self->key->name;
1339   }
1340   const char *key_idstr() {
1341     return pool_id2str($self->pool, $self->key->name);
1342   }
1343   Id type_id() {
1344     return $self->key->type;
1345   }
1346   const char *type_idstr() {
1347     return pool_id2str($self->pool, $self->key->type);
1348   }
1349   Id id() {
1350      return $self->kv.id;
1351   }
1352   const char *idstr() {
1353      return pool_id2str($self->pool, $self->kv.id);
1354   }
1355   const char *str() {
1356      return $self->kv.str;
1357   }
1358   int num() {
1359      return $self->kv.num;
1360   }
1361   int num2() {
1362      return $self->kv.num2;
1363   }
1364   void setpos() {
1365     dataiterator_setpos($self);
1366   }
1367   void setpos_parent() {
1368     dataiterator_setpos_parent($self);
1369   }
1370 }
1371
1372 %extend Pool_solvable_iterator {
1373   Pool_solvable_iterator(Pool *pool) {
1374     Pool_solvable_iterator *s;
1375     s = solv_calloc(1, sizeof(*s));
1376     s->pool = pool;
1377     return s;
1378   }
1379 #if defined(SWIGPYTHON)
1380   %newobject __iter__;
1381   Pool_solvable_iterator *__iter__() {
1382     Pool_solvable_iterator *s;
1383     s = solv_calloc(1, sizeof(*s));
1384     *s = *$self;
1385     return s;
1386   }
1387   %rename("next") __next__();
1388   %exception __next__ {
1389     $action
1390     if (!result) {
1391       PyErr_SetString(PyExc_StopIteration,"no more matches");
1392       return NULL;
1393     }
1394   }
1395 #endif
1396
1397 #ifdef SWIGPERL
1398   perliter(solv::Pool_solvable_iterator)
1399 #endif
1400   %newobject __next__;
1401   XSolvable *__next__() {
1402     Pool *pool = $self->pool;
1403     if ($self->id >= pool->nsolvables)
1404       return 0;
1405     while (++$self->id < pool->nsolvables)
1406       if (pool->solvables[$self->id].repo)
1407         return new_XSolvable(pool, $self->id);
1408     return 0;
1409   }
1410 #ifdef SWIGRUBY
1411   void each() {
1412     XSolvable *n;
1413     while ((n = Pool_solvable_iterator___next__($self)) != 0) {
1414       rb_yield(SWIG_NewPointerObj(SWIG_as_voidptr(n), SWIGTYPE_p_XSolvable, SWIG_POINTER_OWN | 0));
1415     }
1416   }
1417 #endif
1418   %newobject __getitem__;
1419   XSolvable *__getitem__(Id key) {
1420     Pool *pool = $self->pool;
1421     if (key > 0 && key < pool->nsolvables && pool->solvables[key].repo)
1422       return new_XSolvable(pool, key);
1423     return 0;
1424   }
1425   int __len__() {
1426     return $self->pool->nsolvables;
1427   }
1428 }
1429
1430 %extend Pool_repo_iterator {
1431   Pool_repo_iterator(Pool *pool) {
1432     Pool_repo_iterator *s;
1433     s = solv_calloc(1, sizeof(*s));
1434     s->pool = pool;
1435     return s;
1436   }
1437 #if defined(SWIGPYTHON)
1438   %newobject __iter__;
1439   Pool_repo_iterator *__iter__() {
1440     Pool_repo_iterator *s;
1441     s = solv_calloc(1, sizeof(*s));
1442     *s = *$self;
1443     return s;
1444   }
1445   %rename("next") __next__();
1446   %exception __next__ {
1447     $action
1448     if (!result) {
1449       PyErr_SetString(PyExc_StopIteration,"no more matches");
1450       return NULL;
1451     }
1452   }
1453 #endif
1454   %newobject __next__;
1455   Repo *__next__() {
1456     Pool *pool = $self->pool;
1457     if ($self->id >= pool->nrepos + 1)
1458       return 0;
1459     while (++$self->id < pool->nrepos + 1) {
1460       Repo *r = pool_id2repo(pool, $self->id);
1461       if (r)
1462         return r;
1463     }
1464     return 0;
1465   }
1466 #ifdef SWIGRUBY
1467   void each() {
1468     Repo *n;
1469     while ((n = Pool_repo_iterator___next__($self)) != 0) {
1470       rb_yield(SWIG_NewPointerObj(SWIG_as_voidptr(n), SWIGTYPE_p__Repo, SWIG_POINTER_OWN | 0));
1471     }
1472   }
1473 #endif
1474   Repo *__getitem__(Id key) {
1475     Pool *pool = $self->pool;
1476     if (key > 0 && key < pool->nrepos + 1)
1477       return pool_id2repo(pool, key);
1478     return 0;
1479   }
1480   int __len__() {
1481     return $self->pool->nrepos + 1;
1482   }
1483 }
1484
1485 %extend Repo_solvable_iterator {
1486   Repo_solvable_iterator(Repo *repo) {
1487     Repo_solvable_iterator *s;
1488     s = solv_calloc(1, sizeof(*s));
1489     s->repo = repo;
1490     return s;
1491   }
1492 #if defined(SWIGPYTHON)
1493   %newobject __iter__;
1494   Repo_solvable_iterator *__iter__() {
1495     Repo_solvable_iterator *s;
1496     s = solv_calloc(1, sizeof(*s));
1497     *s = *$self;
1498     return s;
1499   }
1500   %rename("next") __next__();
1501   %exception __next__ {
1502     $action
1503     if (!result) {
1504       PyErr_SetString(PyExc_StopIteration,"no more matches");
1505       return NULL;
1506     }
1507   }
1508 #endif
1509   %newobject __next__;
1510   XSolvable *__next__() {
1511     Repo *repo = $self->repo;
1512     Pool *pool = repo->pool;
1513     if (repo->start > 0 && $self->id < repo->start)
1514       $self->id = repo->start - 1;
1515     if ($self->id >= repo->end)
1516       return 0;
1517     while (++$self->id < repo->end)
1518       if (pool->solvables[$self->id].repo == repo)
1519         return new_XSolvable(pool, $self->id);
1520     return 0;
1521   }
1522 #ifdef SWIGRUBY
1523   void each() {
1524     XSolvable *n;
1525     while ((n = Repo_solvable_iterator___next__($self)) != 0) {
1526       rb_yield(SWIG_NewPointerObj(SWIG_as_voidptr(n), SWIGTYPE_p_XSolvable, SWIG_POINTER_OWN | 0));
1527     }
1528   }
1529 #endif
1530   %newobject __getitem__;
1531   XSolvable *__getitem__(Id key) {
1532     Repo *repo = $self->repo;
1533     Pool *pool = repo->pool;
1534     if (key > 0 && key < pool->nsolvables && pool->solvables[key].repo == repo)
1535       return new_XSolvable(pool, key);
1536     return 0;
1537   }
1538   int __len__() {
1539     return $self->repo->pool->nsolvables;
1540   }
1541 }
1542
1543 %extend Dep {
1544   Dep(Pool *pool, Id id) {
1545     Dep *s;
1546     if (!id)
1547       return 0;
1548     s = solv_calloc(1, sizeof(*s));
1549     s->pool = pool;
1550     s->id = id;
1551     return s;
1552   }
1553   const char *str() {
1554     return pool_dep2str($self->pool, $self->id);
1555   }
1556   bool __eq__(Dep *s) {
1557     return $self->pool == s->pool && $self->id == s->id;
1558   }
1559   bool __ne__(Dep *s) {
1560     return !Dep___eq__($self, s);
1561   }
1562 #if defined(SWIGPERL)
1563   %rename("str") __str__;
1564 #endif
1565   const char *__str__() {
1566     return pool_dep2str($self->pool, $self->id);
1567   }
1568   %newobject __repr__;
1569   const char *__repr__() {
1570     char buf[20];
1571     sprintf(buf, "<Id #%d ", $self->id);
1572     return solv_dupjoin(buf, pool_dep2str($self->pool, $self->id), ">");
1573   }
1574 }
1575
1576 %extend XSolvable {
1577   XSolvable(Pool *pool, Id id) {
1578     XSolvable *s;
1579     if (!id || id >= pool->nsolvables)
1580       return 0;
1581     s = solv_calloc(1, sizeof(*s));
1582     s->pool = pool;
1583     s->id = id;
1584     return s;
1585   }
1586   const char *str() {
1587     return pool_solvid2str($self->pool, $self->id);
1588   }
1589   const char *lookup_str(Id keyname) {
1590     return pool_lookup_str($self->pool, $self->id, keyname);
1591   }
1592   Id lookup_id(Id keyname) {
1593     return pool_lookup_id($self->pool, $self->id, keyname);
1594   }
1595   unsigned int lookup_num(Id keyname, unsigned int notfound = 0) {
1596     return pool_lookup_num($self->pool, $self->id, keyname, notfound);
1597   }
1598   bool lookup_void(Id keyname) {
1599     return pool_lookup_void($self->pool, $self->id, keyname);
1600   }
1601   %newobject lookup_checksum;
1602   Chksum *lookup_checksum(Id keyname) {
1603     Id type = 0;
1604     const unsigned char *b = pool_lookup_bin_checksum($self->pool, $self->id, keyname, &type);
1605     return solv_chksum_create_from_bin(type, b);
1606   }
1607   const char *lookup_location(unsigned int *OUTPUT) {
1608     return solvable_get_location($self->pool->solvables + $self->id, OUTPUT);
1609   }
1610 #ifdef SWIGRUBY
1611   %rename("installable?") installable;
1612 #endif
1613   bool installable() {
1614     return pool_installable($self->pool, pool_id2solvable($self->pool, $self->id));
1615   }
1616 #ifdef SWIGRUBY
1617   %rename("isinstalled?") isinstalled;
1618 #endif
1619   bool isinstalled() {
1620     Pool *pool = $self->pool;
1621     return pool->installed && pool_id2solvable(pool, $self->id)->repo == pool->installed;
1622   }
1623
1624   const char * const name;
1625   %{
1626     SWIGINTERN const char *XSolvable_name_get(XSolvable *xs) {
1627       Pool *pool = xs->pool;
1628       return pool_id2str(pool, pool->solvables[xs->id].name);
1629     }
1630   %}
1631   Id const nameid;
1632   %{
1633     SWIGINTERN Id XSolvable_nameid_get(XSolvable *xs) {
1634       return xs->pool->solvables[xs->id].name;
1635     }
1636   %}
1637   const char * const evr;
1638   %{
1639     SWIGINTERN const char *XSolvable_evr_get(XSolvable *xs) {
1640       Pool *pool = xs->pool;
1641       return pool_id2str(pool, pool->solvables[xs->id].evr);
1642     }
1643   %}
1644   Id const evrid;
1645   %{
1646     SWIGINTERN Id XSolvable_evrid_get(XSolvable *xs) {
1647       return xs->pool->solvables[xs->id].evr;
1648     }
1649   %}
1650   const char * const arch;
1651   %{
1652     SWIGINTERN const char *XSolvable_arch_get(XSolvable *xs) {
1653       Pool *pool = xs->pool;
1654       return pool_id2str(pool, pool->solvables[xs->id].arch);
1655     }
1656   %}
1657   Id const archid;
1658   %{
1659     SWIGINTERN Id XSolvable_archid_get(XSolvable *xs) {
1660       return xs->pool->solvables[xs->id].arch;
1661     }
1662   %}
1663   const char * const vendor;
1664   %{
1665     SWIGINTERN const char *XSolvable_vendor_get(XSolvable *xs) {
1666       Pool *pool = xs->pool;
1667       return pool_id2str(pool, pool->solvables[xs->id].vendor);
1668     }
1669   %}
1670   Id const vendorid;
1671   %{
1672     SWIGINTERN Id XSolvable_vendorid_get(XSolvable *xs) {
1673       return xs->pool->solvables[xs->id].vendor;
1674     }
1675   %}
1676   Repo * const repo;
1677   %{
1678     SWIGINTERN Repo *XSolvable_repo_get(XSolvable *xs) {
1679       return xs->pool->solvables[xs->id].repo;
1680     }
1681   %}
1682
1683   bool __eq__(XSolvable *s) {
1684     return $self->pool == s->pool && $self->id == s->id;
1685   }
1686   bool __ne__(XSolvable *s) {
1687     return !XSolvable___eq__($self, s);
1688   }
1689 #if defined(SWIGPERL)
1690   %rename("str") __str__;
1691 #endif
1692   const char *__str__() {
1693     return pool_solvid2str($self->pool, $self->id);
1694   }
1695   %newobject __repr__;
1696   const char *__repr__() {
1697     char buf[20];
1698     sprintf(buf, "<Solvable #%d ", $self->id);
1699     return solv_dupjoin(buf, pool_solvid2str($self->pool, $self->id), ">");
1700   }
1701 }
1702
1703 %extend Problem {
1704   Problem(Solver *solv, Id id) {
1705     Problem *p;
1706     p = solv_calloc(1, sizeof(*p));
1707     p->solv = solv;
1708     p->id = id;
1709     return p;
1710   }
1711   %newobject findproblemrule;
1712   XRule *findproblemrule() {
1713     Id r = solver_findproblemrule($self->solv, $self->id);
1714     return new_XRule($self->solv, r);
1715   }
1716   %newobject findallproblemrules;
1717   %typemap(out) Queue findallproblemrules Queue2Array(XRule *, 1, new_XRule(arg1->solv, id));
1718   Queue findallproblemrules(int unfiltered=0) {
1719     Solver *solv = $self->solv;
1720     Id probr;
1721     int i, j;
1722     Queue q;
1723     queue_init(&q);
1724     solver_findallproblemrules(solv, $self->id, &q);
1725     if (!unfiltered)
1726       {
1727         for (i = j = 0; i < q.count; i++)
1728           {
1729             probr = q.elements[i];
1730             if ((probr >= solv->updaterules && probr < solv->updaterules_end) || (probr >= solv->jobrules && probr < solv->jobrules_end))
1731               continue;
1732             q.elements[j++] = probr;
1733           }
1734         if (j)
1735           queue_truncate(&q, j);
1736       }
1737     return q;
1738   }
1739   int solution_count() {
1740     return solver_solution_count($self->solv, $self->id);
1741   }
1742   %newobject solutions;
1743   %typemap(out) Queue solutions Queue2Array(Solution *, 1, new_Solution(arg1, id));
1744   Queue solutions() {
1745     Queue q;
1746     int i, cnt;
1747     queue_init(&q);
1748     cnt = solver_solution_count($self->solv, $self->id);
1749     for (i = 1; i <= cnt; i++)
1750       queue_push(&q, i);
1751     return q;
1752   }
1753 }
1754
1755 %extend Solution {
1756   Solution(Problem *p, Id id) {
1757     Solution *s;
1758     s = solv_calloc(1, sizeof(*s));
1759     s->solv = p->solv;
1760     s->problemid = p->id;
1761     s->id = id;
1762     return s;
1763   }
1764   int element_count() {
1765     return solver_solutionelement_count($self->solv, $self->problemid, $self->id);
1766   }
1767
1768   %newobject elements;
1769   %typemap(out) Queue elements Queue2Array(Solutionelement *, 4, new_Solutionelement(arg1->solv, arg1->problemid, arg1->id, id, idp[1], idp[2], idp[3]));
1770   Queue elements(bool expandreplaces=0) {
1771     Queue q;
1772     int i, cnt;
1773     queue_init(&q);
1774     cnt = solver_solutionelement_count($self->solv, $self->problemid, $self->id);
1775     for (i = 1; i <= cnt; i++)
1776       {
1777         Id p, rp, type;
1778         solver_next_solutionelement($self->solv, $self->problemid, $self->id, i - 1, &p, &rp);
1779         if (p > 0) {
1780           type = rp ? SOLVER_SOLUTION_REPLACE : SOLVER_SOLUTION_ERASE;
1781         } else {
1782           type = p;
1783           p = rp;
1784           rp = 0;
1785         }
1786         if (type == SOLVER_SOLUTION_REPLACE && expandreplaces) {
1787           int illegal = policy_is_illegal(self->solv, self->solv->pool->solvables + p, self->solv->pool->solvables + rp, 0);
1788           if (illegal) {
1789             if ((illegal & POLICY_ILLEGAL_DOWNGRADE) != 0) {
1790               queue_push2(&q, i, SOLVER_SOLUTION_REPLACE_DOWNGRADE);
1791               queue_push2(&q, p, rp);
1792             }
1793             if ((illegal & POLICY_ILLEGAL_ARCHCHANGE) != 0) {
1794               queue_push2(&q, i, SOLVER_SOLUTION_REPLACE_ARCHCHANGE);
1795               queue_push2(&q, p, rp);
1796             }
1797             if ((illegal & POLICY_ILLEGAL_VENDORCHANGE) != 0) {
1798               queue_push2(&q, i, SOLVER_SOLUTION_REPLACE_VENDORCHANGE);
1799               queue_push2(&q, p, rp);
1800             }
1801             continue;
1802           }
1803         }
1804         queue_push2(&q, i, type);
1805         queue_push2(&q, p, rp);
1806       }
1807     return q;
1808   }
1809 }
1810
1811 %extend Solutionelement {
1812   Solutionelement(Solver *solv, Id problemid, Id solutionid, Id id, Id type, Id p, Id rp) {
1813     Solutionelement *e;
1814     e = solv_calloc(1, sizeof(*e));
1815     e->solv = solv;
1816     e->problemid = problemid;
1817     e->solutionid = id;
1818     e->id = id;
1819     e->type = type;
1820     e->p = p;
1821     e->rp = rp;
1822     return e;
1823   }
1824   const char *str() {
1825     Id p = $self->type;
1826     Id rp = $self->p;
1827     if (p == SOLVER_SOLUTION_ERASE)
1828       {
1829         p = rp;
1830         rp = 0;
1831       }
1832     else if (p == SOLVER_SOLUTION_REPLACE)
1833       {
1834         p = rp;
1835         rp = $self->rp;
1836       }
1837     else if (p == SOLVER_SOLUTION_REPLACE_DOWNGRADE)
1838       return pool_tmpjoin($self->solv->pool, "allow ", policy_illegal2str($self->solv, POLICY_ILLEGAL_DOWNGRADE, $self->solv->pool->solvables + $self->p, $self->solv->pool->solvables + $self->rp), 0);
1839     else if (p == SOLVER_SOLUTION_REPLACE_ARCHCHANGE)
1840       return pool_tmpjoin($self->solv->pool, "allow ", policy_illegal2str($self->solv, POLICY_ILLEGAL_ARCHCHANGE, $self->solv->pool->solvables + $self->p, $self->solv->pool->solvables + $self->rp), 0);
1841     else if (p == SOLVER_SOLUTION_REPLACE_VENDORCHANGE)
1842       return pool_tmpjoin($self->solv->pool, "allow ", policy_illegal2str($self->solv, POLICY_ILLEGAL_VENDORCHANGE, $self->solv->pool->solvables + $self->p, $self->solv->pool->solvables + $self->rp), 0);
1843     return solver_solutionelement2str($self->solv, p, rp);
1844   }
1845   %newobject replaceelements;
1846   %typemap(out) Queue replaceelements Queue2Array(Solutionelement *, 1, new_Solutionelement(arg1->solv, arg1->problemid, arg1->solutionid, arg1->id, id, arg1->p, arg1->rp));
1847   Queue replaceelements() {
1848     Queue q;
1849     int illegal;
1850
1851     queue_init(&q);
1852     if ($self->type != SOLVER_SOLUTION_REPLACE || $self->p <= 0 || $self->rp <= 0)
1853       illegal = 0;
1854     else
1855       illegal = policy_is_illegal($self->solv, $self->solv->pool->solvables + $self->p, $self->solv->pool->solvables + $self->rp, 0);
1856     if ((illegal & POLICY_ILLEGAL_DOWNGRADE) != 0)
1857       queue_push(&q, SOLVER_SOLUTION_REPLACE_DOWNGRADE);
1858     if ((illegal & POLICY_ILLEGAL_ARCHCHANGE) != 0)
1859       queue_push(&q, SOLVER_SOLUTION_REPLACE_ARCHCHANGE);
1860     if ((illegal & POLICY_ILLEGAL_VENDORCHANGE) != 0)
1861       queue_push(&q, SOLVER_SOLUTION_REPLACE_VENDORCHANGE);
1862     if (!q.count)
1863       queue_push(&q, $self->type);
1864     return q;
1865   }
1866   int illegalreplace() {
1867     if ($self->type != SOLVER_SOLUTION_REPLACE || $self->p <= 0 || $self->rp <= 0)
1868       return 0;
1869     return policy_is_illegal($self->solv, $self->solv->pool->solvables + $self->p, $self->solv->pool->solvables + $self->rp, 0);
1870   }
1871   %newobject solvable;
1872   XSolvable * const solvable;
1873   %newobject replacement;
1874   XSolvable * const replacement;
1875   int const jobidx;
1876   %{
1877     SWIGINTERN XSolvable *Solutionelement_solvable_get(Solutionelement *e) {
1878       return new_XSolvable(e->solv->pool, e->p);
1879     }
1880     SWIGINTERN XSolvable *Solutionelement_replacement_get(Solutionelement *e) {
1881       return new_XSolvable(e->solv->pool, e->rp);
1882     }
1883     SWIGINTERN int Solutionelement_jobidx_get(Solutionelement *e) {
1884       return (e->p - 1) / 2;
1885     }
1886   %}
1887   %newobject Job;
1888   Job *Job() {
1889     if ($self->type == SOLVER_SOLUTION_INFARCH || $self->type == SOLVER_SOLUTION_DISTUPGRADE)
1890       return new_Job($self->solv->pool, SOLVER_INSTALL|SOLVER_SOLVABLE, $self->p);
1891     if ($self->type == SOLVER_SOLUTION_REPLACE || $self->type == SOLVER_SOLUTION_REPLACE_DOWNGRADE || $self->type == SOLVER_SOLUTION_REPLACE_ARCHCHANGE || $self->type == SOLVER_SOLUTION_REPLACE_VENDORCHANGE)
1892       return new_Job($self->solv->pool, SOLVER_INSTALL|SOLVER_SOLVABLE, $self->rp);
1893     if ($self->type == SOLVER_SOLUTION_ERASE)
1894       return new_Job($self->solv->pool, SOLVER_ERASE|SOLVER_SOLVABLE, $self->p);
1895     return 0;
1896   }
1897 }
1898
1899 %extend Solver {
1900   static const int SOLVER_RULE_UNKNOWN = SOLVER_RULE_UNKNOWN;
1901   static const int SOLVER_RULE_RPM = SOLVER_RULE_RPM;
1902   static const int SOLVER_RULE_RPM_NOT_INSTALLABLE = SOLVER_RULE_RPM_NOT_INSTALLABLE;
1903   static const int SOLVER_RULE_RPM_NOTHING_PROVIDES_DEP = SOLVER_RULE_RPM_NOTHING_PROVIDES_DEP;
1904   static const int SOLVER_RULE_RPM_PACKAGE_REQUIRES = SOLVER_RULE_RPM_PACKAGE_REQUIRES;
1905   static const int SOLVER_RULE_RPM_SELF_CONFLICT = SOLVER_RULE_RPM_SELF_CONFLICT;
1906   static const int SOLVER_RULE_RPM_PACKAGE_CONFLICT = SOLVER_RULE_RPM_PACKAGE_CONFLICT;
1907   static const int SOLVER_RULE_RPM_SAME_NAME = SOLVER_RULE_RPM_SAME_NAME;
1908   static const int SOLVER_RULE_RPM_PACKAGE_OBSOLETES = SOLVER_RULE_RPM_PACKAGE_OBSOLETES;
1909   static const int SOLVER_RULE_RPM_IMPLICIT_OBSOLETES = SOLVER_RULE_RPM_IMPLICIT_OBSOLETES;
1910   static const int SOLVER_RULE_RPM_INSTALLEDPKG_OBSOLETES = SOLVER_RULE_RPM_INSTALLEDPKG_OBSOLETES;
1911   static const int SOLVER_RULE_UPDATE = SOLVER_RULE_UPDATE;
1912   static const int SOLVER_RULE_FEATURE = SOLVER_RULE_FEATURE;
1913   static const int SOLVER_RULE_JOB = SOLVER_RULE_JOB;
1914   static const int SOLVER_RULE_JOB_NOTHING_PROVIDES_DEP = SOLVER_RULE_JOB_NOTHING_PROVIDES_DEP;
1915   static const int SOLVER_RULE_DISTUPGRADE = SOLVER_RULE_DISTUPGRADE;
1916   static const int SOLVER_RULE_INFARCH = SOLVER_RULE_INFARCH;
1917   static const int SOLVER_RULE_CHOICE = SOLVER_RULE_CHOICE;
1918   static const int SOLVER_RULE_LEARNT = SOLVER_RULE_LEARNT;
1919
1920   static const int SOLVER_SOLUTION_JOB = SOLVER_SOLUTION_JOB;
1921   static const int SOLVER_SOLUTION_INFARCH = SOLVER_SOLUTION_INFARCH;
1922   static const int SOLVER_SOLUTION_DISTUPGRADE = SOLVER_SOLUTION_DISTUPGRADE;
1923   static const int SOLVER_SOLUTION_ERASE = SOLVER_SOLUTION_ERASE;
1924   static const int SOLVER_SOLUTION_REPLACE = SOLVER_SOLUTION_REPLACE;
1925   static const int SOLVER_SOLUTION_REPLACE_DOWNGRADE = SOLVER_SOLUTION_REPLACE_DOWNGRADE;
1926   static const int SOLVER_SOLUTION_REPLACE_ARCHCHANGE = SOLVER_SOLUTION_REPLACE_ARCHCHANGE;
1927   static const int SOLVER_SOLUTION_REPLACE_VENDORCHANGE = SOLVER_SOLUTION_REPLACE_VENDORCHANGE;
1928
1929   static const int POLICY_ILLEGAL_DOWNGRADE = POLICY_ILLEGAL_DOWNGRADE;
1930   static const int POLICY_ILLEGAL_ARCHCHANGE = POLICY_ILLEGAL_ARCHCHANGE;
1931   static const int POLICY_ILLEGAL_VENDORCHANGE = POLICY_ILLEGAL_VENDORCHANGE;
1932
1933   ~Solver() {
1934     solver_free($self);
1935   }
1936 #if defined(SWIGPYTHON)
1937   %pythoncode {
1938     def solve(self, jobs):
1939       j = []
1940       for job in jobs: j += [job.how, job.what]
1941       return self.solve_helper(j)
1942   }
1943 #endif
1944 #if defined(SWIGPERL)
1945   %perlcode {
1946     sub solv::Solver::solve {
1947       my ($self, $jobs) = @_;
1948       my @j = map {($_->{'how'}, $_->{'what'})} @$jobs;
1949       return $self->solve_helper(\@j);
1950     }
1951   }
1952 #endif
1953 #if defined(SWIGRUBY)
1954 %init %{
1955 rb_eval_string(
1956     "class Solv::Solver\n"
1957     "  def solve(jobs)\n"
1958     "    jl = []\n"
1959     "    jobs.each do |j| ; jl << j.how << j.what ; end\n"
1960     "    solve_helper(jl)\n"
1961     "  end\n"
1962     "end\n"
1963   );
1964 %}
1965 #endif
1966   %typemap(out) Queue solve_helper Queue2Array(Problem *, 1, new_Problem(arg1, id));
1967   %newobject solve_helper;
1968   Queue solve_helper(Queue jobs) {
1969     Queue q;
1970     int i, cnt;
1971     queue_init(&q);
1972     solver_solve($self, &jobs);
1973     cnt = solver_problem_count($self);
1974     for (i = 1; i <= cnt; i++)
1975       queue_push(&q, i);
1976     return q;
1977   }
1978   %newobject transaction;
1979   Transaction *transaction() {
1980     return solver_create_transaction($self);
1981   }
1982 }
1983
1984 %extend Transaction {
1985   static const int SOLVER_TRANSACTION_IGNORE = SOLVER_TRANSACTION_IGNORE;
1986   static const int SOLVER_TRANSACTION_ERASE = SOLVER_TRANSACTION_ERASE;
1987   static const int SOLVER_TRANSACTION_REINSTALLED = SOLVER_TRANSACTION_REINSTALLED;
1988   static const int SOLVER_TRANSACTION_DOWNGRADED = SOLVER_TRANSACTION_DOWNGRADED;
1989   static const int SOLVER_TRANSACTION_CHANGED = SOLVER_TRANSACTION_CHANGED;
1990   static const int SOLVER_TRANSACTION_UPGRADED = SOLVER_TRANSACTION_UPGRADED;
1991   static const int SOLVER_TRANSACTION_OBSOLETED = SOLVER_TRANSACTION_OBSOLETED;
1992   static const int SOLVER_TRANSACTION_INSTALL = SOLVER_TRANSACTION_INSTALL;
1993   static const int SOLVER_TRANSACTION_REINSTALL = SOLVER_TRANSACTION_REINSTALL;
1994   static const int SOLVER_TRANSACTION_DOWNGRADE = SOLVER_TRANSACTION_DOWNGRADE;
1995   static const int SOLVER_TRANSACTION_CHANGE = SOLVER_TRANSACTION_CHANGE;
1996   static const int SOLVER_TRANSACTION_UPGRADE = SOLVER_TRANSACTION_UPGRADE;
1997   static const int SOLVER_TRANSACTION_OBSOLETES = SOLVER_TRANSACTION_OBSOLETES;
1998   static const int SOLVER_TRANSACTION_MULTIINSTALL = SOLVER_TRANSACTION_MULTIINSTALL;
1999   static const int SOLVER_TRANSACTION_MULTIREINSTALL = SOLVER_TRANSACTION_MULTIREINSTALL;
2000   static const int SOLVER_TRANSACTION_MAXTYPE = SOLVER_TRANSACTION_MAXTYPE;
2001   static const int SOLVER_TRANSACTION_SHOW_ACTIVE = SOLVER_TRANSACTION_SHOW_ACTIVE;
2002   static const int SOLVER_TRANSACTION_SHOW_ALL = SOLVER_TRANSACTION_SHOW_ALL;
2003   static const int SOLVER_TRANSACTION_SHOW_OBSOLETES = SOLVER_TRANSACTION_SHOW_OBSOLETES;
2004   static const int SOLVER_TRANSACTION_SHOW_MULTIINSTALL = SOLVER_TRANSACTION_SHOW_MULTIINSTALL;
2005   static const int SOLVER_TRANSACTION_CHANGE_IS_REINSTALL = SOLVER_TRANSACTION_CHANGE_IS_REINSTALL;
2006   static const int SOLVER_TRANSACTION_MERGE_VENDORCHANGES = SOLVER_TRANSACTION_MERGE_VENDORCHANGES;
2007   static const int SOLVER_TRANSACTION_MERGE_ARCHCHANGES = SOLVER_TRANSACTION_MERGE_ARCHCHANGES;
2008   static const int SOLVER_TRANSACTION_RPM_ONLY = SOLVER_TRANSACTION_RPM_ONLY;
2009   static const int SOLVER_TRANSACTION_ARCHCHANGE = SOLVER_TRANSACTION_ARCHCHANGE;
2010   static const int SOLVER_TRANSACTION_VENDORCHANGE = SOLVER_TRANSACTION_VENDORCHANGE;
2011   static const int SOLVER_TRANSACTION_KEEP_ORDERDATA = SOLVER_TRANSACTION_KEEP_ORDERDATA;
2012   ~Transaction() {
2013     transaction_free($self);
2014   }
2015 #ifdef SWIGRUBY
2016   %rename("isempty?") isempty;
2017 #endif
2018   bool isempty() {
2019     return $self->steps.count == 0;
2020   }
2021
2022   %newobject othersolvable;
2023   XSolvable *othersolvable(XSolvable *s) {
2024     Id op = transaction_obs_pkg($self, s->id);
2025     return new_XSolvable($self->pool, op);
2026   }
2027
2028   %newobject allothersolvables;
2029   %typemap(out) Queue allothersolvables Queue2Array(XSolvable *, 1, new_XSolvable(arg1->pool, id));
2030   Queue allothersolvables(XSolvable *s) {
2031     Queue q;
2032     queue_init(&q);
2033     transaction_all_obs_pkgs($self, s->id, &q);
2034     return q;
2035   }
2036
2037   %typemap(out) Queue classify Queue2Array(TransactionClass *, 4, new_TransactionClass(arg1, arg2, id, idp[1], idp[2], idp[3]));
2038   %newobject classify;
2039   Queue classify(int mode = 0) {
2040     Queue q;
2041     queue_init(&q);
2042     transaction_classify($self, mode, &q);
2043     return q;
2044   }
2045
2046   %typemap(out) Queue newpackages Queue2Array(XSolvable *, 1, new_XSolvable(arg1->pool, id));
2047   %newobject newpackages;
2048   Queue newpackages() {
2049     Queue q;
2050     int cut;
2051     queue_init(&q);
2052     cut = transaction_installedresult(self, &q);
2053     queue_truncate(&q, cut);
2054     return q;
2055   }
2056
2057   %typemap(out) Queue keptpackages Queue2Array(XSolvable *, 1, new_XSolvable(arg1->pool, id));
2058   %newobject keptpackages;
2059   Queue keptpackages() {
2060     Queue q;
2061     int cut;
2062     queue_init(&q);
2063     cut = transaction_installedresult(self, &q);
2064     if (cut)
2065       queue_deleten(&q, 0, cut);
2066     return q;
2067   }
2068
2069   %typemap(out) Queue steps Queue2Array(XSolvable *, 1, new_XSolvable(arg1->pool, id));
2070   %newobject steps ;
2071   Queue steps() {
2072     Queue q;
2073     queue_init_clone(&q, &$self->steps);
2074     return q;
2075   }
2076
2077   int steptype(XSolvable *s, int mode) {
2078     return transaction_type($self, s->id, mode);
2079   }
2080   int calc_installsizechange() {
2081     return transaction_calc_installsizechange($self);
2082   }
2083   void order(int flags) {
2084     transaction_order($self, flags);
2085   }
2086 }
2087
2088 %extend TransactionClass {
2089   TransactionClass(Transaction *trans, int mode, Id type, int count, Id fromid, Id toid) {
2090     TransactionClass *cl = solv_calloc(1, sizeof(*cl));
2091     cl->transaction = trans;
2092     cl->mode = mode;
2093     cl->type = type;
2094     cl->count = count;
2095     cl->fromid = fromid;
2096     cl->toid = toid;
2097     return cl;
2098   }
2099   %newobject solvables;
2100   %typemap(out) Queue solvables Queue2Array(XSolvable *, 1, new_XSolvable(arg1->transaction->pool, id));
2101   Queue solvables() {
2102     Queue q;
2103     queue_init(&q);
2104     transaction_classify_pkgs($self->transaction, $self->mode, $self->type, $self->fromid, $self->toid, &q);
2105     return q;
2106   }
2107 }
2108
2109 %extend XRule {
2110   XRule(Solver *solv, Id id) {
2111     if (!id)
2112       return 0;
2113     XRule *xr = solv_calloc(1, sizeof(*xr));
2114     xr->solv = solv;
2115     xr->id = id;
2116     return xr;
2117   }
2118   Ruleinfo *info() {
2119     Id type, source, target, dep;
2120     type =  solver_ruleinfo($self->solv, $self->id, &source, &target, &dep);
2121     return new_Ruleinfo($self, type, source, target, dep);
2122   }
2123   %typemap(out) Queue allinfos Queue2Array(Ruleinfo *, 4, new_Ruleinfo(arg1, id, idp[1], idp[2], idp[3]));
2124   %newobject allinfos;
2125   Queue allinfos() {
2126     Queue q;
2127     queue_init(&q);
2128     solver_allruleinfos($self->solv, $self->id, &q);
2129     return q;
2130   }
2131
2132   bool __eq__(XRule *xr) {
2133     return $self->solv == xr->solv && $self->id == xr->id;
2134   }
2135   bool __ne__(XRule *xr) {
2136     return !XRule___eq__($self, xr);
2137   }
2138   %newobject __repr__;
2139   const char *__repr__() {
2140     char buf[20];
2141     sprintf(buf, "<Rule #%d>", $self->id);
2142     return strdup(buf);
2143   }
2144 }
2145
2146 %extend Ruleinfo {
2147   Ruleinfo(XRule *r, Id type, Id source, Id target, Id dep) {
2148     Ruleinfo *ri = solv_calloc(1, sizeof(*ri));
2149     ri->solv = r->solv;
2150     ri->rid = r->id;
2151     ri->type = type;
2152     ri->source = source;
2153     ri->target = target;
2154     ri->dep = dep;
2155     return ri;
2156   }
2157   XSolvable * const solvable;
2158   XSolvable * const othersolvable;
2159   %{
2160     SWIGINTERN XSolvable *Ruleinfo_solvable_get(Ruleinfo *ri) {
2161       return new_XSolvable(ri->solv->pool, ri->source);
2162     }
2163     SWIGINTERN XSolvable *Ruleinfo_othersolvable_get(Ruleinfo *ri) {
2164       return new_XSolvable(ri->solv->pool, ri->target);
2165     }
2166   %}
2167   const char *problemstr() {
2168     return solver_problemruleinfo2str($self->solv, $self->type, $self->source, $self->target, $self->dep);
2169   }
2170 }
2171
2172 %extend XRepodata {
2173   XRepodata(Repo *repo, Id id) {
2174     XRepodata *xr = solv_calloc(1, sizeof(*xr));
2175     xr->repo = repo;
2176     xr->id = id;
2177     return xr;
2178   }
2179   Id new_handle() {
2180     return repodata_new_handle($self->repo->repodata + $self->id);
2181   }
2182   void set_id(Id solvid, Id keyname, Id id) {
2183     repodata_set_id($self->repo->repodata + $self->id, solvid, keyname, id);
2184   }
2185   void set_str(Id solvid, Id keyname, const char *str) {
2186     repodata_set_str($self->repo->repodata + $self->id, solvid, keyname, str);
2187   }
2188   void set_poolstr(Id solvid, Id keyname, const char *str) {
2189     repodata_set_poolstr($self->repo->repodata + $self->id, solvid, keyname, str);
2190   }
2191   void add_idarray(Id solvid, Id keyname, Id id) {
2192     repodata_add_idarray($self->repo->repodata + $self->id, solvid, keyname, id);
2193   }
2194   void add_flexarray(Id solvid, Id keyname, Id handle) {
2195     repodata_add_flexarray($self->repo->repodata + $self->id, solvid, keyname, handle);
2196   }
2197   void set_checksum(Id solvid, Id keyname, Chksum *chksum) {
2198     const unsigned char *buf = solv_chksum_get(chksum, 0);
2199     if (buf)
2200       repodata_set_bin_checksum($self->repo->repodata + $self->id, solvid, keyname, solv_chksum_get_type(chksum), buf);
2201   }
2202   const char *lookup_str(Id solvid, Id keyname) {
2203     return repodata_lookup_str($self->repo->repodata + $self->id, solvid, keyname);
2204   }
2205   Queue lookup_idarray(Id solvid, Id keyname) {
2206     Queue r;
2207     queue_init(&r);
2208     repodata_lookup_idarray($self->repo->repodata + $self->id, solvid, keyname, &r);
2209     return r;
2210   }
2211   %newobject lookup_checksum;
2212   Chksum *lookup_checksum(Id solvid, Id keyname) {
2213     Id type = 0;
2214     const unsigned char *b = repodata_lookup_bin_checksum($self->repo->repodata + $self->id, solvid, keyname, &type);
2215     return solv_chksum_create_from_bin(type, b);
2216   }
2217   void internalize() {
2218     repodata_internalize($self->repo->repodata + $self->id);
2219   }
2220   void create_stubs() {
2221     repodata_create_stubs($self->repo->repodata + $self->id);
2222   }
2223   void write(FILE *fp) {
2224     repodata_write($self->repo->repodata + $self->id, fp, repo_write_stdkeyfilter, 0);
2225   }
2226   bool add_solv(FILE *fp, int flags = 0) {
2227     Repodata *data = $self->repo->repodata + $self->id;
2228     int r, oldstate = data->state;
2229     data->state = REPODATA_LOADING;
2230     r = repo_add_solv_flags(data->repo, fp, flags | REPO_USE_LOADING);
2231     if (r || data->state == REPODATA_LOADING)
2232       data->state = oldstate;
2233     return r;
2234   }
2235   void extend_to_repo() {
2236     Repodata *data = $self->repo->repodata + $self->id;
2237     repodata_extend_block(data, data->repo->start, data->repo->end - data->repo->start);
2238   }
2239   bool __eq__(XRepodata *xr) {
2240     return $self->repo == xr->repo && $self->id == xr->id;
2241   }
2242   bool __ne__(XRepodata *xr) {
2243     return !XRepodata___eq__($self, xr);
2244   }
2245   %newobject __repr__;
2246   const char *__repr__() {
2247     char buf[20];
2248     sprintf(buf, "<Repodata #%d>", $self->id);
2249     return strdup(buf);
2250   }
2251 }
2252