4237ff8090cf76dc9e4eea9d5496b669cfff703f
[platform/upstream/libsolv.git] / examples / 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 #if defined(SWIGPYTHON)
19 %typemap(in) Queue {
20   /* Check if is a list */
21   queue_init(&$1);
22   if (PyList_Check($input)) {
23     int size = PyList_Size($input);
24     int i = 0;
25     for (i = 0; i < size; i++) {
26       PyObject *o = PyList_GetItem($input,i);
27       int v;
28       int e = SWIG_AsVal_int(o, &v);
29       if (!SWIG_IsOK(e)) {
30         SWIG_exception_fail(SWIG_ArgError(e), "list must contain only integers");
31         queue_free(&$1);
32         return NULL;
33       }
34       queue_push(&$1, v);
35     }
36   } else {
37     PyErr_SetString(PyExc_TypeError,"not a list");
38     return NULL;
39   }
40 }
41 %typemap(out) Queue {
42   int i;
43   PyObject *o = PyList_New($1.count);
44   for (i = 0; i < $1.count; i++)
45     PyList_SetItem(o, i, SWIG_From_int($1.elements[i]));
46   queue_free(&$1);
47   $result = o;
48 }
49 #endif
50 #if defined(SWIGPERL)
51 %typemap(in) Queue {
52   AV *av;
53   int i, size;
54   queue_init(&$1);
55   if (!SvROK($input) || SvTYPE(SvRV($input)) != SVt_PVAV)
56     SWIG_croak("Argument $argnum is not an array reference.");
57   av = (AV*)SvRV($input);
58   size = av_len(av);
59   for (i = 0; i <= size; i++) {
60     SV **sv = av_fetch(av, i, 0);
61     int v;
62     int e = SWIG_AsVal_int(*sv, &v);
63     if (!SWIG_IsOK(e)) {
64       SWIG_croak("list must contain only integers");
65     }
66     queue_push(&$1, v);
67   }
68 }
69 # AV *o = newAV();
70 # av_push(o, SvREFCNT_inc(SWIG_From_int($1.elements[i])));
71 # $result = newRV_noinc((SV*)o); argvi++;
72 #
73 %typemap(out) Queue {
74   int i;
75   if (argvi + $1.count + 1>= items) {
76     EXTEND(sp, items - (argvi + $1.count + 1) + 1);
77   }
78   for (i = 0; i < $1.count; i++)
79     ST(argvi++) = SvREFCNT_inc(SWIG_From_int($1.elements[i]));
80   queue_free(&$1);
81   $result = 0;
82 }
83 #endif
84 %typemap(arginit) Queue {
85   queue_init(&$1);
86 }
87 %typemap(freearg) Queue {
88   queue_free(&$1);
89 }
90
91 #if defined(SWIGPERL)
92
93 # work around a swig bug
94 %{
95 #undef SWIG_CALLXS
96 #ifdef PERL_OBJECT 
97 #  define SWIG_CALLXS(_name) TOPMARK=MARK-PL_stack_base;_name(cv,pPerl) 
98 #else 
99 #  ifndef MULTIPLICITY 
100 #    define SWIG_CALLXS(_name) TOPMARK=MARK-PL_stack_base;_name(cv) 
101 #  else 
102 #    define SWIG_CALLXS(_name) TOPMARK=MARK-PL_stack_base;_name(PERL_GET_THX, cv) 
103 #  endif 
104 #endif 
105 %}
106
107
108 %define perliter(class)
109   %perlcode {
110     sub class##::FETCH {
111       my $i = ${##class##::ITERATORS}{$_[0]};
112       if ($i) {
113         $_[1] == $i->[0] - 1 ? $i->[1] : undef;
114       } else {
115         $_[0]->__getitem__($_[1]);
116       }
117     }
118     sub class##::FETCHSIZE {
119       my $i = ${##class##::ITERATORS}{$_[0]};
120       if ($i) {
121         ($i->[1] = $_[0]->__next__()) ? ++$i->[0]  : 0;
122       } else {
123         $_[0]->__len__();
124       }
125     }
126   }
127 %enddef
128
129 %{
130
131 #define SWIG_PERL_ITERATOR      0x80
132
133 SWIGRUNTIMEINLINE SV *
134 SWIG_Perl_NewArrayObj(SWIG_MAYBE_PERL_OBJECT void *ptr, swig_type_info *t, int flags) {
135   SV *result = sv_newmortal();
136   if (ptr && (flags & (SWIG_SHADOW | SWIG_POINTER_OWN))) {
137     SV *self;
138     SV *obj=newSV(0);
139     AV *array=newAV();
140     HV *stash;
141     sv_setref_pv(obj, (char *) SWIG_Perl_TypeProxyName(t), ptr);
142     stash=SvSTASH(SvRV(obj));
143     if (flags & SWIG_POINTER_OWN) {
144       HV *hv;
145       GV *gv=*(GV**)hv_fetch(stash, "OWNER", 5, TRUE);
146       if (!isGV(gv))
147         gv_init(gv, stash, "OWNER", 5, FALSE);
148       hv=GvHVn(gv);
149       hv_store_ent(hv, obj, newSViv(1), 0);
150     }
151     if (flags & SWIG_PERL_ITERATOR) {
152       HV *hv;
153       GV *gv=*(GV**)hv_fetch(stash, "ITERATORS", 9, TRUE);
154       AV *av=newAV();
155       if (!isGV(gv))
156         gv_init(gv, stash, "ITERATORS", 9, FALSE);
157       hv=GvHVn(gv);
158       hv_store_ent(hv, obj, newRV_inc((SV *)av), 0);
159     }
160     sv_magic((SV *)array, (SV *)obj, 'P', Nullch, 0);
161     SvREFCNT_dec(obj);
162     self=newRV_noinc((SV *)array);
163     sv_setsv(result, self);
164     SvREFCNT_dec((SV *)self);
165     sv_bless(result, stash);
166   } else {
167     sv_setref_pv(result, (char *) SWIG_Perl_TypeProxyName(t), ptr);
168   }
169   return result;
170 }
171
172 %}
173
174 %typemap(out) Perlarray {
175   ST(argvi) = SWIG_Perl_NewArrayObj(SWIG_PERL_OBJECT_CALL SWIG_as_voidptr(result), $1_descriptor, $owner | $shadow); argvi++;
176 }
177 %typemap(out) Perliterator {
178   ST(argvi) = SWIG_Perl_NewArrayObj(SWIG_PERL_OBJECT_CALL SWIG_as_voidptr(result), $1_descriptor, $owner | $shadow | SWIG_PERL_ITERATOR); argvi++;
179 }
180
181 %typemap(out) Pool_solvable_iterator * = Perlarray;
182 %typemap(out) Pool_solvable_iterator * solvables_iter = Perliterator;
183 %typemap(out) Pool_repo_iterator * = Perlarray;
184 %typemap(out) Pool_repo_iterator * repos_iter = Perliterator;
185 %typemap(out) Repo_solvable_iterator * = Perlarray;
186 %typemap(out) Repo_solvable_iterator * solvables_iter = Perliterator;
187 %typemap(out) Dataiterator * = Perliterator;
188
189 #endif
190
191
192
193 #if defined(SWIGPYTHON)
194 typedef PyObject *AppObjectPtr;
195 %typemap(out) AppObjectPtr {
196   $result = $1;
197   Py_INCREF($result);
198 }
199 #endif
200 #if defined(SWIGPERL)
201 typedef SV *AppObjectPtr;
202 %typemap(in) AppObjectPtr {
203   $1 = SvROK($input) ? SvRV($input) : 0;
204 }
205 %typemap(out) AppObjectPtr {
206   $result = $1 ? newRV_inc($1) : newSV(0);
207   argvi++;
208 }
209 #endif
210 #if defined(SWIGRUBY)
211 typedef VALUE AppObjectPtr;
212 #endif
213
214
215 %include "cdata.i"
216 #ifndef SWIGPERL
217 %include "file.i"
218 #endif
219 %include "typemaps.i"
220
221 %{
222 #include "stdio.h"
223 #include "pool.h"
224 #include "solver.h"
225 #include "policy.h"
226 #include "solverdebug.h"
227 #include "repo_solv.h"
228 #include "chksum.h"
229
230 #include "repo_rpmdb.h"
231 #include "repo_rpmmd.h"
232 #include "repo_write.h"
233 #include "repo_products.h"
234 #include "repo_susetags.h"
235 #include "repo_updateinfoxml.h"
236 #include "repo_deltainfoxml.h"
237 #include "repo_repomdxml.h"
238 #include "repo_content.h"
239 #include "sat_xfopen.h"
240
241 #define true 1
242 #define false 1
243
244 #define SOLVER_SOLUTION_ERASE -100
245 #define SOLVER_SOLUTION_REPLACE -101
246 typedef struct chksum Chksum;
247 typedef int bool;
248 typedef void *AppObjectPtr;
249
250 typedef struct {
251   Pool* pool;
252   Id id;
253 } XSolvable;
254
255 typedef struct {
256   Solver* solv;
257   Id id;
258 } XRule;
259
260 typedef struct {
261   Repo* repo;
262   Id id;
263 } XRepodata;
264
265 typedef struct {
266   Pool *pool;
267   Id id;
268 } Pool_solvable_iterator;
269
270 typedef struct {
271   Pool *pool;
272   Id id;
273 } Pool_repo_iterator;
274
275 typedef struct {
276   Repo *repo;
277   Id id;
278 } Repo_solvable_iterator;
279
280 typedef struct {
281   Pool *pool;
282   Id how;
283   Id what;
284 } Job;
285
286 typedef struct {
287   Solver *solv;
288   Id id;
289 } Problem;
290
291 typedef struct {
292   Solver *solv;
293   Id problemid;
294   Id id;
295 } Solution;
296
297 typedef struct {
298   Solver *solv;
299   Id problemid;
300   Id solutionid;
301   Id id;
302
303   Id type;
304   Id p;
305   Id rp;
306 } Solutionelement;
307
308 typedef struct {
309   Solver *solv;
310   Id rid;
311   Id type;
312   Id source;
313   Id target;
314   Id dep;
315 } Ruleinfo;
316
317 typedef Dataiterator Datamatch;
318
319 %}
320
321 typedef int Id;
322
323 %include "knownid.h"
324
325 # from repodata.h
326 %constant Id SOLVID_META;
327 %constant Id SOLVID_POS;
328
329 %constant int REL_EQ;
330 %constant int REL_GT;
331 %constant int REL_LT;
332 %constant int REL_ARCH;
333
334
335 typedef struct {
336   Pool* const pool;
337   Id const id;
338 } XSolvable;
339
340 %nodefaultctor Ruleinfo;
341 typedef struct {
342   Solver* const solv;
343   Id const type;
344   Id const dep;
345 } Ruleinfo;
346
347 typedef struct {
348   Solver* const solv;
349   Id const id;
350 } XRule;
351
352 typedef struct {
353   Repo* const repo;
354   Id const id;
355 } XRepodata;
356
357 # put before pool/repo so we can access the constructor
358 %nodefaultdtor Dataiterator;
359 typedef struct {} Dataiterator;
360 typedef struct {} Pool_solvable_iterator;
361 typedef struct {} Pool_repo_iterator;
362 typedef struct {} Repo_solvable_iterator;
363
364 %nodefaultctor Datamatch;
365 %nodefaultdtor Datamatch;
366 typedef struct {
367   Pool * const pool;
368   Repo * const repo;
369   const Id solvid;
370 } Datamatch;
371
372 typedef struct {
373   Pool * const pool;
374   Id how;
375   Id what;
376 } Job;
377
378 %nodefaultctor Pool;
379 %nodefaultdtor Pool;
380 typedef struct {
381   AppObjectPtr appdata;
382 } Pool;
383
384 %nodefaultctor Repo;
385 %nodefaultdtor Repo;
386 typedef struct _Repo {
387   Pool * const pool;
388   const char * const name;
389   int priority;
390   int subpriority;
391   int const nsolvables;
392   AppObjectPtr appdata;
393 } Repo;
394
395 %nodefaultctor Solver;
396 %nodefaultdtor Solver;
397 typedef struct {
398   Pool * const pool;
399   bool fixsystem;
400   bool allowdowngrade;
401   bool allowarchchange;
402   bool allowvendorchange;
403   bool allowuninstall;
404   bool updatesystem;
405   bool noupdateprovide;
406   bool dosplitprovides;
407   bool dontinstallrecommended;
408   bool ignorealreadyrecommended;
409   bool dontshowinstalledrecommended;
410   bool distupgrade;
411   bool distupgrade_removeunsupported;
412   bool noinfarchcheck;
413 } Solver;
414
415 typedef struct chksum {
416 } Chksum;
417
418 %rename(xfopen) sat_xfopen;
419 %rename(xfopen_fd) sat_xfopen_fd;
420 %rename(xfclose) sat_xfclose;
421 %rename(xfileno) sat_xfileno;
422
423 FILE *sat_xfopen(const char *fn, const char *mode = 0);
424 FILE *sat_xfopen_fd(const char *fn, int fd, const char *mode = 0);
425 %inline {
426   int sat_xfclose(FILE *fp) {
427     return fclose(fp);
428   }
429   int sat_xfileno(FILE *fp) {
430     return fileno(fp);
431   }
432 }
433
434 typedef struct {
435   Solver * const solv;
436   Id const id;
437 } Problem;
438
439 typedef struct {
440   Solver * const solv;
441   Id const problemid;
442   Id const id;
443 } Solution;
444
445 typedef struct {
446   Solver *const solv;
447   Id const problemid;
448   Id const solutionid;
449   Id const id;
450   Id const type;
451 } Solutionelement;
452
453 %nodefaultctor Transaction;
454 %nodefaultdtor Transaction;
455 typedef struct {
456   Pool * const pool;
457 } Transaction;
458
459
460
461 %extend Job {
462   static const Id SOLVER_SOLVABLE = SOLVER_SOLVABLE;
463   static const Id SOLVER_SOLVABLE_NAME = SOLVER_SOLVABLE_NAME;
464   static const Id SOLVER_SOLVABLE_PROVIDES = SOLVER_SOLVABLE_PROVIDES;
465   static const Id SOLVER_SOLVABLE_ONE_OF = SOLVER_SOLVABLE_ONE_OF;
466   static const Id SOLVER_SOLVABLE_REPO = SOLVER_SOLVABLE_REPO;
467   static const Id SOLVER_SOLVABLE_ALL = SOLVER_SOLVABLE_ALL;
468   static const Id SOLVER_SELECTMASK = SOLVER_SELECTMASK;
469   static const Id SOLVER_NOOP = SOLVER_NOOP;
470   static const Id SOLVER_INSTALL = SOLVER_INSTALL;
471   static const Id SOLVER_ERASE = SOLVER_ERASE;
472   static const Id SOLVER_UPDATE = SOLVER_UPDATE;
473   static const Id SOLVER_WEAKENDEPS = SOLVER_WEAKENDEPS;
474   static const Id SOLVER_NOOBSOLETES = SOLVER_NOOBSOLETES;
475   static const Id SOLVER_LOCK = SOLVER_LOCK;
476   static const Id SOLVER_DISTUPGRADE = SOLVER_DISTUPGRADE;
477   static const Id SOLVER_VERIFY = SOLVER_VERIFY;
478   static const Id SOLVER_DROP_ORPHANED = SOLVER_DROP_ORPHANED;
479   static const Id SOLVER_USERINSTALLED = SOLVER_USERINSTALLED;
480   static const Id SOLVER_JOBMASK = SOLVER_JOBMASK;
481   static const Id SOLVER_WEAK = SOLVER_WEAK;
482   static const Id SOLVER_ESSENTIAL = SOLVER_ESSENTIAL;
483   static const Id SOLVER_CLEANDEPS = SOLVER_CLEANDEPS;
484   static const Id SOLVER_SETEV = SOLVER_SETEV;
485   static const Id SOLVER_SETEVR = SOLVER_SETEVR;
486   static const Id SOLVER_SETARCH = SOLVER_SETARCH;
487   static const Id SOLVER_SETVENDOR = SOLVER_SETVENDOR;
488   static const Id SOLVER_SETREPO = SOLVER_SETREPO;
489   static const Id SOLVER_NOAUTOSET = SOLVER_NOAUTOSET;
490   static const Id SOLVER_SETMASK = SOLVER_SETMASK;
491
492   Job(Pool *pool, Id how, Id what) {
493     Job *job = sat_calloc(1, sizeof(*job));
494     job->pool = pool;
495     job->how = how;
496     job->what = what;
497     return job;
498   }
499
500   const char *str() {
501     return pool_job2str($self->pool, $self->how, $self->what, 0);
502   }
503 }
504
505 %extend Chksum {
506   Chksum(Id type) {
507     return (Chksum *)sat_chksum_create(type);
508   }
509   Chksum(Id type, const char *hex) {
510     unsigned char buf[64];
511     int l = sat_chksum_len(type);
512     if (!l)
513       return 0;
514     if (sat_hex2bin(&hex, buf, sizeof(buf)) != l || hex[0])
515       return 0;
516     return (Chksum *)sat_chksum_create_from_bin(type, buf);
517   }
518   ~Chksum() {
519     sat_chksum_free($self, 0);
520   }
521   Id const type;
522   %{
523   SWIGINTERN Id Chksum_type_get(Chksum *chksum) {
524     return sat_chksum_get_type(chksum);
525   }
526   %}
527   void add(const char *str) {
528     sat_chksum_add($self, str, strlen((char *)str));
529   }
530   void add_fp(FILE *fp) {
531     char buf[4096];
532     int l;
533     while ((l = fread(buf, 1, sizeof(buf), fp)) > 0)
534       sat_chksum_add($self, buf, l);
535     rewind(fp);         /* convenience */
536   }
537   void add_fd(int fd) {
538     char buf[4096];
539     int l;
540     while ((l = read(fd, buf, sizeof(buf))) > 0)
541       sat_chksum_add($self, buf, l);
542     lseek(fd, 0, 0);    /* convenience */
543   }
544   void add_stat(const char *filename) {
545     struct stat stb;
546     if (stat(filename, &stb))
547       memset(&stb, 0, sizeof(stb));
548     sat_chksum_add($self, &stb.st_dev, sizeof(stb.st_dev));
549     sat_chksum_add($self, &stb.st_ino, sizeof(stb.st_ino));
550     sat_chksum_add($self, &stb.st_size, sizeof(stb.st_size));
551     sat_chksum_add($self, &stb.st_mtime, sizeof(stb.st_mtime));
552   }
553   bool matches(Chksum *othersum) {
554     int l;
555     const unsigned char *b, *bo;
556     if (!othersum)
557       return 0;
558     if (sat_chksum_get_type($self) != sat_chksum_get_type(othersum))
559       return 0;
560     b = sat_chksum_get($self, &l);
561     bo = sat_chksum_get(othersum, 0);
562     return memcmp(b, bo, l) == 0;
563   }
564   SWIGCDATA raw() {
565     int l;
566     const unsigned char *b;
567     b = sat_chksum_get($self, &l);
568     return cdata_void((void *)b, l);
569   }
570   %newobject hex;
571   char *hex() {
572     int l;
573     const unsigned char *b;
574     char *ret, *rp;
575
576     b = sat_chksum_get($self, &l);
577     ret = sat_malloc(2 * l + 1);
578     sat_bin2hex(b, l, ret);
579     return ret;
580   }
581 }
582
583
584
585 %extend Pool {
586   Pool() {
587     Pool *pool = pool_create();
588     return pool;
589   }
590   ~Pool() {
591   }
592   void set_debuglevel(int level) {
593     pool_setdebuglevel($self, level);
594   }
595 #if defined(SWIGPYTHON)
596   %{
597   SWIGINTERN int loadcallback(Pool *pool, Repodata *data, void *d) {
598     XRepodata *xd = new_XRepodata(data->repo, data - data->repo->repodata);
599     PyObject *args = Py_BuildValue("(O)", SWIG_NewPointerObj(SWIG_as_voidptr(xd), SWIGTYPE_p_XRepodata, SWIG_POINTER_OWN | 0));
600     PyObject *result = PyEval_CallObject((PyObject *)d, args);
601     int ecode = 0;
602     int vresult = 0;
603     Py_DECREF(args);
604     if (!result)
605       return 0; /* exception */
606     ecode = SWIG_AsVal_int(result, &vresult);
607     Py_DECREF(result);
608     return SWIG_IsOK(ecode) ? vresult : 0;
609   }
610   %}
611   void set_loadcallback(PyObject *callable) {
612     if ($self->loadcallback == loadcallback)
613       Py_DECREF($self->loadcallbackdata);
614     if (callable)
615       Py_INCREF(callable);
616     pool_setloadcallback($self, callable ? loadcallback : 0, callable);
617   }
618 #endif
619 #if defined(SWIGPERL)
620   %{
621
622 SWIGINTERN int loadcallback(Pool *pool, Repodata *data, void *d) {
623   int count;
624   int ret = 0;
625   dSP;
626   XRepodata *xd = new_XRepodata(data->repo, data - data->repo->repodata);
627
628   ENTER;
629   SAVETMPS;
630   PUSHMARK(SP);
631   XPUSHs(SWIG_NewPointerObj(SWIG_as_voidptr(xd), SWIGTYPE_p_XRepodata, SWIG_OWNER | SWIG_SHADOW));
632   PUTBACK;
633   count = perl_call_sv((SV *)d, G_EVAL|G_SCALAR);
634   SPAGAIN;
635   if (count)
636     ret = POPi;
637   PUTBACK;
638   FREETMPS;
639   LEAVE;
640   return ret;
641 }
642
643   %}
644   void set_loadcallback(SV *callable) {
645     if ($self->loadcallback == loadcallback)
646       SvREFCNT_dec($self->loadcallbackdata);
647     if (callable)
648       SvREFCNT_inc(callable);
649     pool_setloadcallback($self, callable ? loadcallback : 0, callable);
650   }
651 #endif
652
653   void free() {
654 #if defined(SWIGPYTHON) || defined(SWIGPERL)
655     Pool_set_loadcallback($self, 0);
656 #endif
657     pool_free($self);
658   }
659   Id str2id(const char *str, int create=1) {
660     return str2id($self, str, create);
661   }
662   const char *id2str(Id id) {
663     return id2str($self, id);
664   }
665   const char *dep2str(Id id) {
666     return dep2str($self, id);
667   }
668   Id rel2id(Id name, Id evr, int flags, int create=1) {
669     return rel2id($self, name, evr, flags, create);
670   }
671   Id id2langid(Id id, const char *lang, int create=1) {
672     return pool_id2langid($self, id, lang, create);
673   }
674   void setarch(const char *arch) {
675     pool_setarch($self, arch);
676   }
677   Repo *add_repo(const char *name) {
678     return repo_create($self, name);
679   }
680   const char *lookup_str(Id entry, Id keyname) {
681     return pool_lookup_str($self, entry, keyname);
682   }
683   Id lookup_id(Id entry, Id keyname) {
684     return pool_lookup_id($self, entry, keyname);
685   }
686   unsigned int lookup_num(Id entry, Id keyname, unsigned int notfound = 0) {
687     return pool_lookup_num($self, entry, keyname, notfound);
688   }
689   bool lookup_void(Id entry, Id keyname) {
690     return pool_lookup_void($self, entry, keyname);
691   }
692   %newobject lookup_checksum;
693   Chksum *lookup_checksum(Id entry, Id keyname) {
694     Id type = 0;
695     const unsigned char *b = pool_lookup_bin_checksum($self, entry, keyname, &type);
696     return sat_chksum_create_from_bin(type, b);
697   }
698
699   %newobject Dataiterator;
700   Dataiterator *Dataiterator(Id p, Id key, const char *match, int flags) {
701     return new_Dataiterator($self, 0, p, key, match, flags);
702   }
703   const char *solvid2str(Id solvid) {
704     return solvid2str($self, solvid);
705   }
706   void addfileprovides() {
707     pool_addfileprovides($self);
708   }
709   Queue addfileprovides_ids() {
710     Queue r;
711     Id *addedfileprovides = 0;
712     queue_init(&r);
713     pool_addfileprovides_ids($self, $self->installed, &addedfileprovides);
714     if (addedfileprovides) {
715       for (; *addedfileprovides; addedfileprovides++)
716         queue_push(&r, *addedfileprovides);
717     }
718     return r;
719   }
720   void createwhatprovides() {
721     pool_createwhatprovides($self);
722   }
723
724   %newobject solvables;
725   Pool_solvable_iterator * const solvables;
726   %{
727   SWIGINTERN Pool_solvable_iterator * Pool_solvables_get(Pool *pool) {
728     return new_Pool_solvable_iterator(pool);
729   }
730   %}
731   %newobject solvables_iter;
732   Pool_solvable_iterator * solvables_iter() {
733     return new_Pool_solvable_iterator($self);
734   }
735
736   %newobject repos;
737   Pool_repo_iterator * const repos;
738   %{
739   SWIGINTERN Pool_repo_iterator * Pool_repos_get(Pool *pool) {
740     return new_Pool_repo_iterator(pool);
741   }
742   %}
743   %newobject repos_iter;
744   Pool_repo_iterator * repos_iter() {
745     return new_Pool_repo_iterator($self);
746   }
747
748   Repo *installed;
749   %{
750   SWIGINTERN void Pool_installed_set(Pool *pool, Repo *installed) {
751     pool_set_installed(pool, installed);
752   }
753   Repo *Pool_installed_get(Pool *pool) {
754     return pool->installed;
755   }
756   %}
757
758   Queue providerids(Id dep) {
759     Pool *pool = $self;
760     Queue q;
761     Id p, pp;
762     queue_init(&q);
763     FOR_PROVIDES(p, pp, dep)
764       queue_push(&q, p);
765     return q;
766   }
767   Queue matchprovidingids(const char *match, int flags) {
768     Pool *pool = $self;
769     Queue q;
770     Id id;
771     queue_init(&q);
772     if (!flags) {
773       for (id = 1; id < pool->ss.nstrings; id++)
774         if (pool->whatprovides[id])
775           queue_push(&q, id);
776     } else {
777       Datamatcher ma;
778       if (!datamatcher_init(&ma, match, flags)) {
779         for (id = 1; id < pool->ss.nstrings; id++)
780           if (pool->whatprovides[id] && datamatcher_match(&ma, id2str(pool, id)))
781             queue_push(&q, id);
782         datamatcher_free(&ma);
783       }
784     }
785     return q;
786   }
787   # move to job?
788   Queue jobsolvids(Job *job) {
789     Pool *pool = $self;
790     Id p, pp, how;
791     Queue q;
792     queue_init(&q);
793     how = job->how & SOLVER_SELECTMASK;
794     FOR_JOB_SELECT(p, pp, how, job->what)
795       queue_push(&q, p);
796     return q;
797   }
798   Job *Job(Id how, Id what) {
799     return new_Job($self, how, what);
800   }
801
802 #if defined(SWIGPYTHON)
803   %pythoncode {
804     def jobsolvables (self, *args):
805       return [ self.solvables[id] for id in self.jobsolvids(*args) ]
806     def providers(self, *args):
807       return [ self.solvables[id] for id in self.providerids(*args) ]
808   }
809 #endif
810 #if defined(SWIGPERL)
811   %perlcode {
812     sub solv::Pool::jobsolvables {
813       my ($self, @args) = @_;
814       return map {$self->{'solvables'}->[$_]} $self->jobsolvids(@args);
815     }
816     sub solv::Pool::providers {
817       my ($self, @args) = @_;
818       return map {$self->{'solvables'}->[$_]} $self->providerids(@args);
819     }
820   }
821 #endif
822
823   Id towhatprovides(Queue q) {
824     return pool_queuetowhatprovides($self, &q);
825   }
826   bool isknownarch(Id id) {
827     Pool *pool = $self;
828     if (id == ARCH_SRC || id == ARCH_NOSRC || id == ARCH_NOARCH)
829       return 1;
830     if (pool->id2arch && (id > pool->lastarch || !pool->id2arch[id]))
831       return 0;
832     return 1;
833   }
834
835   %newobject create_solver;
836   Solver *create_solver() {
837     return solver_create($self);
838   }
839 }
840
841 %extend Repo {
842   static const int REPO_REUSE_REPODATA = REPO_REUSE_REPODATA;
843   static const int REPO_NO_INTERNALIZE = REPO_NO_INTERNALIZE;
844   static const int REPO_LOCALPOOL = REPO_LOCALPOOL;
845   static const int REPO_USE_LOADING = REPO_USE_LOADING;
846   static const int REPO_EXTEND_SOLVABLES = REPO_EXTEND_SOLVABLES;
847   static const int SOLV_ADD_NO_STUBS = SOLV_ADD_NO_STUBS;       /* repo_solv */
848   static const int SUSETAGS_RECORD_SHARES = SUSETAGS_RECORD_SHARES; /* repo_susetags */
849   static const int SOLV_ADD_NO_STUBS = SOLV_ADD_NO_STUBS ; /* repo_solv */
850
851   void free(int reuseids = 0) {
852     repo_free($self, reuseids);
853   }
854   void empty(int reuseids = 0) {
855     repo_empty($self, reuseids);
856   }
857   bool add_solv(const char *name, int flags = 0) {
858     FILE *fp = fopen(name, "r");
859     if (!fp)
860       return 0;
861     int r = repo_add_solv_flags($self, fp, flags);
862     fclose(fp);
863     return r == 0;
864   }
865   bool add_solv(FILE *fp, int flags = 0) {
866     return repo_add_solv_flags($self, fp, flags) == 0;
867   }
868   bool add_products(const char *proddir, int flags = 0) {
869     repo_add_products($self, proddir, 0, flags);
870     return 1;
871   }
872   bool add_rpmmd(FILE *fp, const char *language, int flags = 0) {
873     repo_add_rpmmd($self, fp, language, flags);
874     return 1;
875   }
876   bool add_rpmdb(Repo *ref, int flags = 0) {
877     repo_add_rpmdb($self, ref, 0, flags);
878     return 1;
879   }
880   Id add_rpm(const char *name, int flags = 0) {
881     return repo_add_rpm($self, name, flags);
882   }
883   bool add_susetags(FILE *fp, Id defvendor, const char *language, int flags = 0) {
884     repo_add_susetags($self, fp, defvendor, language, flags);
885     return 1;
886   }
887   bool add_repomdxml(FILE *fp, int flags = 0) {
888     repo_add_repomdxml($self, fp, flags);
889     return 1;
890   }
891   bool add_content(FILE *fp, int flags = 0) {
892     repo_add_content($self, fp, flags);
893     return 1;
894   }
895   bool add_updateinfoxml(FILE *fp, int flags = 0) {
896     repo_add_updateinfoxml($self, fp, flags);
897     return 1;
898   }
899   bool add_deltainfoxml(FILE *fp, int flags = 0) {
900     repo_add_deltainfoxml($self, fp, flags);
901     return 1;
902   }
903   void internalize() {
904     repo_internalize($self);
905   }
906   const char *lookup_str(Id entry, Id keyname) {
907     return repo_lookup_str($self, entry, keyname);
908   }
909   Id lookup_id(Id entry, Id keyname) {
910     return repo_lookup_id($self, entry, keyname);
911   }
912   unsigned int lookup_num(Id entry, Id keyname, unsigned int notfound = 0) {
913     return repo_lookup_num($self, entry, keyname, notfound);
914   }
915   void write(FILE *fp) {
916     repo_write($self, fp, repo_write_stdkeyfilter, 0, 0);
917   }
918   # HACK, remove if no longer needed!
919   bool write_first_repodata(FILE *fp, int flags = 0) {
920     int oldnrepodata = $self->nrepodata;
921     $self->nrepodata = 1;
922     repo_write($self, fp, repo_write_stdkeyfilter, 0, 0);
923     $self->nrepodata = oldnrepodata;
924     return 1;
925   }
926
927   %newobject Dataiterator;
928   Dataiterator *Dataiterator(Id p, Id key, const char *match, int flags) {
929     return new_Dataiterator($self->pool, $self, p, key, match, flags);
930   }
931
932   Id const id;
933   %{
934   SWIGINTERN Id Repo_id_get(Repo *repo) {
935     return repo->repoid;
936   }
937   %}
938   Repo_solvable_iterator * const solvables;
939   %{
940   SWIGINTERN Repo_solvable_iterator * Repo_solvables_get(Repo *repo) {
941     return new_Repo_solvable_iterator(repo);
942   }
943   %}
944   %newobject solvables_iter;
945   Repo_solvable_iterator *solvables_iter() {
946     return new_Repo_solvable_iterator($self);
947   }
948
949   XRepodata *add_repodata(int flags = 0) {
950     Repodata *rd = repo_add_repodata($self, flags);
951     return new_XRepodata($self, rd - $self->repodata);
952   }
953
954   void create_stubs() {
955     Repodata *data;
956     if (!$self->nrepodata)
957       return;
958     data = $self->repodata  + ($self->nrepodata - 1);
959     if (data->state != REPODATA_STUB)
960       repodata_create_stubs(data);
961   }
962   bool iscontiguous() {
963     int i;
964     for (i = $self->start; i < $self->end; i++)
965       if ($self->pool->solvables[i].repo != $self)
966         return 0;
967     return 1;
968   }
969   XRepodata *first_repodata() {
970      int i;
971      if (!$self->nrepodata)
972        return 0;
973      /* make sure all repodatas but the first are extensions */
974      if ($self->repodata[0].loadcallback)
975         return 0;
976      for (i = 1; i < $self->nrepodata; i++)
977        if (!$self->repodata[i].loadcallback)
978          return 0;       /* oops, not an extension */
979      return new_XRepodata($self, 0);
980    }
981 }
982
983 %extend Dataiterator {
984   static const int SEARCH_STRING = SEARCH_STRING;
985   static const int SEARCH_SUBSTRING = SEARCH_SUBSTRING;
986   static const int SEARCH_GLOB = SEARCH_GLOB;
987   static const int SEARCH_REGEX = SEARCH_REGEX;
988   static const int SEARCH_NOCASE = SEARCH_NOCASE;
989   static const int SEARCH_FILES = SEARCH_FILES;
990   static const int SEARCH_COMPLETE_FILELIST = SEARCH_COMPLETE_FILELIST;
991
992   Dataiterator(Pool *pool, Repo *repo, Id p, Id key, const char *match, int flags) {
993     Dataiterator *di = sat_calloc(1, sizeof(*di));
994     dataiterator_init(di, pool, repo, p, key, match, flags);
995     return di;
996   }
997   ~Dataiterator() {
998     dataiterator_free($self);
999     sat_free($self);
1000   }
1001 #if defined(SWIGPYTHON)
1002   %newobject __iter__;
1003   Dataiterator *__iter__() {
1004     Dataiterator *ndi;
1005     ndi = sat_calloc(1, sizeof(*ndi));
1006     dataiterator_init_clone(ndi, $self);
1007     return ndi;
1008   }
1009   %rename("next") __next__();
1010   %exception __next__ {
1011     $action
1012     if (!result) {
1013       PyErr_SetString(PyExc_StopIteration,"no more matches");
1014       return NULL;
1015     }
1016   }
1017 #endif
1018
1019 #ifdef SWIGPERL
1020   perliter(solv::Dataiterator)
1021 #endif
1022
1023   %newobject __next__;
1024   Datamatch *__next__() {
1025     Dataiterator *ndi;
1026     if (!dataiterator_step($self)) {
1027       return 0;
1028     }
1029     ndi = sat_calloc(1, sizeof(*ndi));
1030     dataiterator_init_clone(ndi, $self);
1031     return ndi;
1032   }
1033   void prepend_keyname(Id key) {
1034     dataiterator_prepend_keyname($self, key);
1035   }
1036   void skip_solvable() {
1037     dataiterator_skip_solvable($self);
1038   }
1039 }
1040
1041 %extend Datamatch {
1042   ~Datamatch() {
1043     dataiterator_free($self);
1044     sat_free($self);
1045   }
1046   %newobject solvable;
1047   XSolvable * const solvable;
1048   %{
1049   SWIGINTERN XSolvable *Datamatch_solvable_get(Dataiterator *di) {
1050     return new_XSolvable(di->pool, di->solvid);
1051   }
1052   %}
1053   Id key_id() {
1054     return $self->key->name;
1055   }
1056   const char *key_idstr() {
1057     return id2str($self->pool, $self->key->name);
1058   }
1059   Id keytype_id() {
1060     return $self->key->type;
1061   }
1062   const char *keytype_idstr() {
1063     return id2str($self->pool, $self->key->type);
1064   }
1065   Id match_id() {
1066      return $self->kv.id;
1067   }
1068   const char *match_idstr() {
1069      return id2str($self->pool, $self->kv.id);
1070   }
1071   const char *match_str() {
1072      return $self->kv.str;
1073   }
1074   int match_num() {
1075      return $self->kv.num;
1076   }
1077   int match_num2() {
1078      return $self->kv.num2;
1079   }
1080   void setpos_parent() {
1081     dataiterator_setpos_parent($self);
1082   }
1083 }
1084
1085 %extend Pool_solvable_iterator {
1086   Pool_solvable_iterator(Pool *pool) {
1087     Pool_solvable_iterator *s;
1088     s = sat_calloc(1, sizeof(*s));
1089     s->pool = pool;
1090     return s;
1091   }
1092 #if defined(SWIGPYTHON)
1093   %newobject __iter__;
1094   Pool_solvable_iterator *__iter__() {
1095     Pool_solvable_iterator *s;
1096     s = sat_calloc(1, sizeof(*s));
1097     *s = *$self;
1098     return s;
1099   }
1100   %rename("next") __next__();
1101   %exception __next__ {
1102     $action
1103     if (!result) {
1104       PyErr_SetString(PyExc_StopIteration,"no more matches");
1105       return NULL;
1106     }
1107   }
1108 #endif
1109
1110 #ifdef SWIGPERL
1111   perliter(solv::Pool_solvable_iterator)
1112 #endif
1113   %newobject __next__;
1114   XSolvable *__next__() {
1115     Pool *pool = $self->pool;
1116     XSolvable *s;
1117     if ($self->id >= pool->nsolvables)
1118       return 0;
1119     while (++$self->id < pool->nsolvables)
1120       if (pool->solvables[$self->id].repo)
1121         return new_XSolvable(pool, $self->id);
1122     return 0;
1123   }
1124   %newobject __getitem__;
1125   XSolvable *__getitem__(Id key) {
1126     Pool *pool = $self->pool;
1127     if (key > 0 && key < pool->nsolvables && pool->solvables[key].repo)
1128       return new_XSolvable(pool, key);
1129     return 0;
1130   }
1131   int __len__() {
1132     return $self->pool->nsolvables;
1133   }
1134 }
1135
1136 %extend Pool_repo_iterator {
1137   Pool_repo_iterator(Pool *pool) {
1138     Pool_repo_iterator *s;
1139     s = sat_calloc(1, sizeof(*s));
1140     s->pool = pool;
1141     return s;
1142   }
1143 #if defined(SWIGPYTHON)
1144   %newobject __iter__;
1145   Pool_repo_iterator *__iter__() {
1146     Pool_repo_iterator *s;
1147     s = sat_calloc(1, sizeof(*s));
1148     *s = *$self;
1149     return s;
1150   }
1151   %rename("next") __next__();
1152   %exception __next__ {
1153     $action
1154     if (!result) {
1155       PyErr_SetString(PyExc_StopIteration,"no more matches");
1156       return NULL;
1157     }
1158   }
1159 #endif
1160   %newobject __next__;
1161   Repo *__next__() {
1162     Pool *pool = $self->pool;
1163     if ($self->id >= pool->nrepos + 1)
1164       return 0;
1165     while (++$self->id < pool->nrepos + 1) {
1166       Repo *r = pool_id2repo(pool, $self->id);
1167       if (r)
1168         return r;
1169     }
1170     return 0;
1171   }
1172   Repo *__getitem__(Id key) {
1173     Pool *pool = $self->pool;
1174     if (key > 0 && key < pool->nrepos + 1)
1175       return pool_id2repo(pool, key);
1176     return 0;
1177   }
1178   int __len__() {
1179     return $self->pool->nrepos + 1;
1180   }
1181 }
1182
1183 %extend Repo_solvable_iterator {
1184   Repo_solvable_iterator(Repo *repo) {
1185     Repo_solvable_iterator *s;
1186     s = sat_calloc(1, sizeof(*s));
1187     s->repo = repo;
1188     return s;
1189   }
1190 #if defined(SWIGPYTHON)
1191   %newobject __iter__;
1192   Repo_solvable_iterator *__iter__() {
1193     Repo_solvable_iterator *s;
1194     s = sat_calloc(1, sizeof(*s));
1195     *s = *$self;
1196     return s;
1197   }
1198   %rename("next") __next__();
1199   %exception __next__ {
1200     $action
1201     if (!result) {
1202       PyErr_SetString(PyExc_StopIteration,"no more matches");
1203       return NULL;
1204     }
1205   }
1206 #endif
1207   %newobject __next__;
1208   XSolvable *__next__() {
1209     Repo *repo = $self->repo;
1210     Pool *pool = repo->pool;
1211     XSolvable *s;
1212     if (repo->start > 0 && $self->id < repo->start)
1213       $self->id = repo->start - 1;
1214     if ($self->id >= repo->end)
1215       return 0;
1216     while (++$self->id < repo->end)
1217       if (pool->solvables[$self->id].repo == repo)
1218         return new_XSolvable(pool, $self->id);
1219     return 0;
1220   }
1221   %newobject __getitem__;
1222   XSolvable *__getitem__(Id key) {
1223     Repo *repo = $self->repo;
1224     Pool *pool = repo->pool;
1225     if (key > 0 && key < pool->nsolvables && pool->solvables[key].repo == repo)
1226       return new_XSolvable(pool, key);
1227     return 0;
1228   }
1229   int __len__() {
1230     return $self->repo->pool->nsolvables;
1231   }
1232 }
1233
1234 %extend XSolvable {
1235   XSolvable(Pool *pool, Id id) {
1236     if (!id)
1237       return 0;
1238     XSolvable *s = sat_calloc(1, sizeof(*s));
1239     s->pool = pool;
1240     s->id = id;
1241     return s;
1242   }
1243   const char *str() {
1244     return solvid2str($self->pool, $self->id);
1245   }
1246   const char *lookup_str(Id keyname) {
1247     return pool_lookup_str($self->pool, $self->id, keyname);
1248   }
1249   Id lookup_id(Id keyname) {
1250     return pool_lookup_id($self->pool, $self->id, keyname);
1251   }
1252   unsigned int lookup_num(Id keyname, unsigned int notfound = 0) {
1253     return pool_lookup_num($self->pool, $self->id, keyname, notfound);
1254   }
1255   bool lookup_void(Id keyname) {
1256     return pool_lookup_void($self->pool, $self->id, keyname);
1257   }
1258   %newobject lookup_checksum;
1259   Chksum *lookup_checksum(Id keyname) {
1260     Id type = 0;
1261     const unsigned char *b = pool_lookup_bin_checksum($self->pool, $self->id, keyname, &type);
1262     return sat_chksum_create_from_bin(type, b);
1263   }
1264   const char *lookup_location(int *OUTPUT) {
1265     return solvable_get_location($self->pool->solvables + $self->id, OUTPUT);
1266   }
1267   bool installable() {
1268     return pool_installable($self->pool, pool_id2solvable($self->pool, $self->id));
1269   }
1270   bool isinstalled() {
1271     Pool *pool = $self->pool;
1272     return pool->installed && pool_id2solvable(pool, $self->id)->repo == pool->installed;
1273   }
1274
1275   const char * const name;
1276   %{
1277     SWIGINTERN const char *XSolvable_name_get(XSolvable *xs) {
1278       Pool *pool = xs->pool;
1279       return id2str(pool, pool->solvables[xs->id].name);
1280     }
1281   %}
1282   Id const nameid;
1283   %{
1284     SWIGINTERN Id XSolvable_nameid_get(XSolvable *xs) {
1285       return xs->pool->solvables[xs->id].name;
1286     }
1287   %}
1288   const char * const evr;
1289   %{
1290     SWIGINTERN const char *XSolvable_evr_get(XSolvable *xs) {
1291       Pool *pool = xs->pool;
1292       return id2str(pool, pool->solvables[xs->id].evr);
1293     }
1294   %}
1295   Id const evrid;
1296   %{
1297     SWIGINTERN Id XSolvable_evrid_get(XSolvable *xs) {
1298       return xs->pool->solvables[xs->id].evr;
1299     }
1300   %}
1301   const char * const arch;
1302   %{
1303     SWIGINTERN const char *XSolvable_arch_get(XSolvable *xs) {
1304       Pool *pool = xs->pool;
1305       return id2str(pool, pool->solvables[xs->id].arch);
1306     }
1307   %}
1308   Id const archid;
1309   %{
1310     SWIGINTERN Id XSolvable_archid_get(XSolvable *xs) {
1311       return xs->pool->solvables[xs->id].arch;
1312     }
1313   %}
1314   const char * const vendor;
1315   %{
1316     SWIGINTERN const char *XSolvable_vendor_get(XSolvable *xs) {
1317       Pool *pool = xs->pool;
1318       return id2str(pool, pool->solvables[xs->id].vendor);
1319     }
1320   %}
1321   Id const vendorid;
1322   %{
1323     SWIGINTERN Id XSolvable_vendorid_get(XSolvable *xs) {
1324       return xs->pool->solvables[xs->id].vendor;
1325     }
1326   %}
1327   Repo * const repo;
1328   %{
1329     SWIGINTERN Repo *XSolvable_repo_get(XSolvable *xs) {
1330       return xs->pool->solvables[xs->id].repo;
1331     }
1332   %}
1333 }
1334
1335 %extend Problem {
1336   Problem(Solver *solv, Id id) {
1337     Problem *p;
1338     p = sat_calloc(1, sizeof(*p));
1339     p->solv = solv;
1340     p->id = id;
1341     return p;
1342   }
1343   Id findproblemrule_helper() {
1344     return solver_findproblemrule($self->solv, $self->id);
1345   }
1346   Queue findallproblemrules_helper(int unfiltered=0) {
1347     Solver *solv = $self->solv;
1348     Id probr;
1349     int i, j;
1350     Queue q;
1351     queue_init(&q);
1352     solver_findallproblemrules(solv, $self->id, &q);
1353     if (!unfiltered)
1354       {
1355         for (i = j = 0; i < q.count; i++)
1356           {
1357             probr = q.elements[i];
1358             if ((probr >= solv->updaterules && probr < solv->updaterules_end) || (probr >= solv->jobrules && probr < solv->jobrules_end))
1359               continue;
1360             q.elements[j++] = probr;
1361           }
1362         if (j)
1363           queue_truncate(&q, j);
1364       }
1365     return q;
1366   }
1367   int solution_count() {
1368     return solver_solution_count($self->solv, $self->id);
1369   }
1370 #if defined(SWIGPYTHON)
1371   %pythoncode {
1372     def findproblemrule(self):
1373       return XRule(self.solv, self.findproblemrule_helper())
1374     def findallproblemrules(self, unfiltered=0):
1375       return [ XRule(self.solv, i) for i in self.findallproblemrules_helper(unfiltered) ]
1376     def solutions(self):
1377       return [ Solution(self, i) for i in range(1, self.solution_count() + 1) ];
1378   }
1379 #endif
1380 #if defined(SWIGPERL)
1381   %perlcode {
1382     sub solv::Problem::findproblemrule {
1383       my ($self) = @_;
1384       return solv::XRule->new($self->{'solv'}, $self->findproblemrule_helper());
1385     }
1386     sub solv::Problem::findallproblemrule {
1387       my ($self, $unfiltered) = @_;
1388       return map {solv::XRule->new($self->{'solv'}, $_)} $self->findallproblemrule_helper($unfiltered);
1389     }
1390     sub solv::Problem::solutions {
1391       my ($self) = @_;
1392       return map {solv::Solution->new($self, $_)} 1..($self->solution_count());
1393     }
1394   }
1395 #endif
1396 }
1397
1398 %extend Solution {
1399   Solution(Problem *p, Id id) {
1400     Solution *s;
1401     s = sat_calloc(1, sizeof(*s));
1402     s->solv = p->solv;
1403     s->problemid = p->id;
1404     s->id = id;
1405     return s;
1406   }
1407   int element_count() {
1408     return solver_solutionelement_count($self->solv, $self->problemid, $self->id);
1409   }
1410 #if defined(SWIGPYTHON)
1411   %pythoncode {
1412     def elements(self):
1413       return [ Solutionelement(self, i) for i in range(1, self.element_count() + 1) ];
1414   }
1415 #endif
1416 #if defined(SWIGPERL)
1417   %perlcode {
1418     sub solv::Solution::elements {
1419       my ($self) = @_;
1420       return map {solv::Solutionelement->new($self, $_)} 1..($self->element_count());
1421     }
1422   }
1423 #endif
1424 }
1425
1426 %extend Solutionelement {
1427   Solutionelement(Solution *s, Id id) {
1428     Solutionelement *e;
1429     e = sat_calloc(1, sizeof(*e));
1430     e->solv = s->solv;
1431     e->problemid = s->problemid;
1432     e->solutionid = s->id;
1433     e->id = id;
1434     solver_next_solutionelement(e->solv, e->problemid, e->solutionid, e->id - 1, &e->p, &e->rp);
1435     if (e->p > 0) {
1436       e->type = e->rp ? SOLVER_SOLUTION_REPLACE : SOLVER_SOLUTION_ERASE;
1437     } else {
1438       e->type = e->p;
1439       e->p = e->rp;
1440       e->rp = 0;
1441     }
1442     return e;
1443   }
1444   int illegalreplace() {
1445     if ($self->type != SOLVER_SOLUTION_REPLACE || $self->p <= 0 || $self->rp <= 0)
1446       return 0;
1447     return policy_is_illegal($self->solv, $self->solv->pool->solvables + $self->p, $self->solv->pool->solvables + $self->rp, 0);
1448   }
1449   %newobject solvable;
1450   XSolvable * const solvable;
1451   %newobject replacement;
1452   XSolvable * const replacement;
1453   int const jobidx;
1454   %{
1455     SWIGINTERN XSolvable *Solutionelement_solvable_get(Solutionelement *e) {
1456       return new_XSolvable(e->solv->pool, e->p);
1457     }
1458     SWIGINTERN XSolvable *Solutionelement_replacement_get(Solutionelement *e) {
1459       return new_XSolvable(e->solv->pool, e->rp);
1460     }
1461     SWIGINTERN int Solutionelement_jobidx_get(Solutionelement *e) {
1462       return (e->p - 1) / 2;
1463     }
1464   %}
1465   %newobject Job;
1466   Job *Job() {
1467     if ($self->type == SOLVER_SOLUTION_INFARCH || $self->type == SOLVER_SOLUTION_DISTUPGRADE)
1468       return new_Job($self->solv->pool, SOLVER_INSTALL|SOLVER_SOLVABLE, $self->p);
1469     if ($self->type == SOLVER_SOLUTION_REPLACE)
1470       return new_Job($self->solv->pool, SOLVER_INSTALL|SOLVER_SOLVABLE, $self->rp);
1471     if ($self->type == SOLVER_SOLUTION_ERASE)
1472       return new_Job($self->solv->pool, SOLVER_ERASE|SOLVER_SOLVABLE, $self->p);
1473     return 0;
1474   }
1475 }
1476
1477 %extend Solver {
1478   static const int SOLVER_RULE_UNKNOWN = SOLVER_RULE_UNKNOWN;
1479   static const int SOLVER_RULE_RPM = SOLVER_RULE_RPM;
1480   static const int SOLVER_RULE_RPM_NOT_INSTALLABLE = SOLVER_RULE_RPM_NOT_INSTALLABLE;
1481   static const int SOLVER_RULE_RPM_NOTHING_PROVIDES_DEP = SOLVER_RULE_RPM_NOTHING_PROVIDES_DEP;
1482   static const int SOLVER_RULE_RPM_PACKAGE_REQUIRES = SOLVER_RULE_RPM_PACKAGE_REQUIRES;
1483   static const int SOLVER_RULE_RPM_SELF_CONFLICT = SOLVER_RULE_RPM_SELF_CONFLICT;
1484   static const int SOLVER_RULE_RPM_PACKAGE_CONFLICT = SOLVER_RULE_RPM_PACKAGE_CONFLICT;
1485   static const int SOLVER_RULE_RPM_SAME_NAME = SOLVER_RULE_RPM_SAME_NAME;
1486   static const int SOLVER_RULE_RPM_PACKAGE_OBSOLETES = SOLVER_RULE_RPM_PACKAGE_OBSOLETES;
1487   static const int SOLVER_RULE_RPM_IMPLICIT_OBSOLETES = SOLVER_RULE_RPM_IMPLICIT_OBSOLETES;
1488   static const int SOLVER_RULE_RPM_INSTALLEDPKG_OBSOLETES = SOLVER_RULE_RPM_INSTALLEDPKG_OBSOLETES;
1489   static const int SOLVER_RULE_UPDATE = SOLVER_RULE_UPDATE;
1490   static const int SOLVER_RULE_FEATURE = SOLVER_RULE_FEATURE;
1491   static const int SOLVER_RULE_JOB = SOLVER_RULE_JOB;
1492   static const int SOLVER_RULE_JOB_NOTHING_PROVIDES_DEP = SOLVER_RULE_JOB_NOTHING_PROVIDES_DEP;
1493   static const int SOLVER_RULE_DISTUPGRADE = SOLVER_RULE_DISTUPGRADE;
1494   static const int SOLVER_RULE_INFARCH = SOLVER_RULE_INFARCH;
1495   static const int SOLVER_RULE_CHOICE = SOLVER_RULE_CHOICE;
1496   static const int SOLVER_RULE_LEARNT = SOLVER_RULE_LEARNT;
1497
1498   static const int SOLVER_SOLUTION_JOB = SOLVER_SOLUTION_JOB;
1499   static const int SOLVER_SOLUTION_INFARCH = SOLVER_SOLUTION_INFARCH;
1500   static const int SOLVER_SOLUTION_DISTUPGRADE = SOLVER_SOLUTION_DISTUPGRADE;
1501   static const int SOLVER_SOLUTION_ERASE = SOLVER_SOLUTION_ERASE;
1502   static const int SOLVER_SOLUTION_REPLACE = SOLVER_SOLUTION_REPLACE;
1503
1504   static const int POLICY_ILLEGAL_DOWNGRADE = POLICY_ILLEGAL_DOWNGRADE;
1505   static const int POLICY_ILLEGAL_ARCHCHANGE = POLICY_ILLEGAL_ARCHCHANGE;
1506   static const int POLICY_ILLEGAL_VENDORCHANGE = POLICY_ILLEGAL_VENDORCHANGE;
1507
1508   ~Solver() {
1509     solver_free($self);
1510   }
1511 #if defined(SWIGPYTHON)
1512   %pythoncode {
1513     def solve(self, jobs):
1514       j = []
1515       for job in jobs: j += [job.how, job.what]
1516       nprob = self.solve_helper(j)
1517       return [ Problem(self, pid) for pid in range(1, nprob + 1) ]
1518   }
1519 #endif
1520 #if defined(SWIGPERL)
1521   %perlcode {
1522     sub solv::Solver::solve {
1523       my ($self, $jobs) = @_;
1524       my @j = map {($_->{'how'}, $_->{'what'})} @$jobs;
1525       my $nprob = $self->solve_helper(\@j);
1526       return map {solv::Problem->new($self, $_)} 1..$nprob;
1527     }
1528   }
1529 #endif
1530   int solve_helper(Queue jobs) {
1531     solver_solve($self, &jobs);
1532     return solver_problem_count($self);
1533   }
1534   %newobject transaction;
1535   Transaction *transaction() {
1536     Transaction *t;
1537     t = sat_calloc(1, sizeof(*t));
1538     transaction_init_clone(t, &$self->trans);
1539     return t;
1540   }
1541 }
1542
1543 %extend Transaction {
1544   static const int SOLVER_TRANSACTION_IGNORE = SOLVER_TRANSACTION_IGNORE;
1545   static const int SOLVER_TRANSACTION_ERASE = SOLVER_TRANSACTION_ERASE;
1546   static const int SOLVER_TRANSACTION_REINSTALLED = SOLVER_TRANSACTION_REINSTALLED;
1547   static const int SOLVER_TRANSACTION_DOWNGRADED = SOLVER_TRANSACTION_DOWNGRADED;
1548   static const int SOLVER_TRANSACTION_CHANGED = SOLVER_TRANSACTION_CHANGED;
1549   static const int SOLVER_TRANSACTION_UPGRADED = SOLVER_TRANSACTION_UPGRADED;
1550   static const int SOLVER_TRANSACTION_OBSOLETED = SOLVER_TRANSACTION_OBSOLETED;
1551   static const int SOLVER_TRANSACTION_INSTALL = SOLVER_TRANSACTION_INSTALL;
1552   static const int SOLVER_TRANSACTION_REINSTALL = SOLVER_TRANSACTION_REINSTALL;
1553   static const int SOLVER_TRANSACTION_DOWNGRADE = SOLVER_TRANSACTION_DOWNGRADE;
1554   static const int SOLVER_TRANSACTION_CHANGE = SOLVER_TRANSACTION_CHANGE;
1555   static const int SOLVER_TRANSACTION_UPGRADE = SOLVER_TRANSACTION_UPGRADE;
1556   static const int SOLVER_TRANSACTION_OBSOLETES = SOLVER_TRANSACTION_OBSOLETES;
1557   static const int SOLVER_TRANSACTION_MULTIINSTALL = SOLVER_TRANSACTION_MULTIINSTALL;
1558   static const int SOLVER_TRANSACTION_MULTIREINSTALL = SOLVER_TRANSACTION_MULTIREINSTALL;
1559   static const int SOLVER_TRANSACTION_MAXTYPE = SOLVER_TRANSACTION_MAXTYPE;
1560   static const int SOLVER_TRANSACTION_SHOW_ACTIVE = SOLVER_TRANSACTION_SHOW_ACTIVE;
1561   static const int SOLVER_TRANSACTION_SHOW_ALL = SOLVER_TRANSACTION_SHOW_ALL;
1562   static const int SOLVER_TRANSACTION_SHOW_OBSOLETES = SOLVER_TRANSACTION_SHOW_OBSOLETES;
1563   static const int SOLVER_TRANSACTION_SHOW_MULTIINSTALL = SOLVER_TRANSACTION_SHOW_MULTIINSTALL;
1564   static const int SOLVER_TRANSACTION_CHANGE_IS_REINSTALL = SOLVER_TRANSACTION_CHANGE_IS_REINSTALL;
1565   static const int SOLVER_TRANSACTION_MERGE_VENDORCHANGES = SOLVER_TRANSACTION_MERGE_VENDORCHANGES;
1566   static const int SOLVER_TRANSACTION_MERGE_ARCHCHANGES = SOLVER_TRANSACTION_MERGE_ARCHCHANGES;
1567   static const int SOLVER_TRANSACTION_RPM_ONLY = SOLVER_TRANSACTION_RPM_ONLY;
1568   static const int SOLVER_TRANSACTION_ARCHCHANGE = SOLVER_TRANSACTION_ARCHCHANGE;
1569   static const int SOLVER_TRANSACTION_VENDORCHANGE = SOLVER_TRANSACTION_VENDORCHANGE;
1570   static const int SOLVER_TRANSACTION_KEEP_ORDERDATA = SOLVER_TRANSACTION_KEEP_ORDERDATA;
1571   ~Transaction() {
1572     transaction_free($self);
1573     sat_free($self);
1574   }
1575   bool isempty() {
1576     return $self->steps.count == 0;
1577   }
1578   Queue classify_helper(int mode) {
1579     Queue q;
1580     queue_init(&q);
1581     transaction_classify($self, mode, &q);
1582     return q;
1583   }
1584   Queue classify_pkgs_helper(int mode, Id cl, Id from, Id to) {
1585     Queue q;
1586     queue_init(&q);
1587     transaction_classify_pkgs($self, mode, cl, from, to, &q);
1588     return q;
1589   }
1590   %newobject othersolvable;
1591   XSolvable *othersolvable(XSolvable *s) {
1592     Id op = transaction_obs_pkg($self, s->id);
1593     return new_XSolvable($self->pool, op);
1594   }
1595 #if defined(SWIGPYTHON)
1596   %pythoncode {
1597     def classify(self, mode = 0):
1598       r = []
1599       cr = self.classify_helper(mode)
1600       for type, cnt, fromid, toid in zip(*([iter(cr)] * 4)):
1601         if type != self.SOLVER_TRANSACTION_IGNORE:
1602           r.append([ type, [ self.pool.solvables[j] for j in self.classify_pkgs_helper(mode, type, fromid, toid) ], fromid, toid ])
1603       return r
1604     }
1605 #endif
1606 #if defined(SWIGPERL)
1607   %perlcode {
1608     sub solv::Transaction::classify {
1609       my ($self, $mode) = @_;
1610       $mode ||= 0;
1611       my @r = $self->classify_helper($mode);
1612       my @res;
1613       while (@r) {
1614         my ($type, $cnt, $fromid, $toid) = splice(@r, 0, 4);
1615         next if $type == $solv::Transaction::SOLVER_TRANSACTION_IGNORE;
1616         push @res, [$type, [ map {$self->{'pool'}->{'solvables'}->[$_]} $self->classify_pkgs_helper($mode, $type, $fromid, $toid) ], $fromid, $toid];
1617       }
1618       return @res;
1619     }
1620   }
1621 #endif
1622   Queue newpackages_helper() {
1623     Queue q;
1624     int cut;
1625     queue_init(&q);
1626     cut = transaction_installedresult(self, &q);
1627     queue_truncate(&q, cut);
1628     return q;
1629   }
1630   Queue keptpackages_helper() {
1631     Queue q;
1632     int cut;
1633     queue_init(&q);
1634     cut = transaction_installedresult(self, &q);
1635     if (cut)
1636       queue_deleten(&q, 0, cut);
1637     return q;
1638   }
1639   Queue steps_helper() {
1640     Queue q;
1641     queue_init_clone(&q, &$self->steps);
1642     return q;
1643   }
1644   int steptype(XSolvable *s, int mode) {
1645     return transaction_type($self, s->id, mode);
1646   }
1647 #if defined(SWIGPYTHON)
1648   %pythoncode {
1649     def newpackages(self):
1650       return [ self.pool.solvables[i] for i in self.newpackages_helper() ]
1651     def keptpackages(self):
1652       return [ self.pool.solvables[i] for i in self.keptpackages_helper() ]
1653     def steps(self):
1654       return [ self.pool.solvables[i] for i in self.steps_helper() ]
1655   }
1656 #endif
1657 #if defined(SWIGPERL)
1658   %perlcode {
1659     sub solv::Transaction::newpackages {
1660       my ($self) = @_;
1661       return map {$self->{'pool'}->{'solvables'}->[$_]} $self->newpackages_helper();
1662     }
1663     sub solv::Transaction::keptpackages {
1664       my ($self) = @_;
1665       return map {$self->{'pool'}->{'solvables'}->[$_]} $self->newpackages_helper();
1666     }
1667     sub solv::Transaction::steps {
1668       my ($self) = @_;
1669       return map {$self->{'pool'}->{'solvables'}->[$_]} $self->steps_helper();
1670     }
1671   }
1672 #endif
1673   int calc_installsizechange() {
1674     return transaction_calc_installsizechange($self);
1675   }
1676   void order(int flags) {
1677     transaction_order($self, flags);
1678   }
1679 }
1680
1681 %extend XRule {
1682   XRule(Solver *solv, Id id) {
1683     if (!id)
1684       return 0;
1685     XRule *xr = sat_calloc(1, sizeof(*xr));
1686     xr->solv = solv;
1687     xr->id = id;
1688     return xr;
1689   }
1690   Ruleinfo *info() {
1691     Ruleinfo *ri = sat_calloc(1, sizeof(*ri));
1692     ri->solv = $self->solv;
1693     ri->type = solver_ruleinfo($self->solv, $self->id, &ri->source, &ri->target, &ri->dep);
1694     return ri;
1695   }
1696 }
1697
1698 %extend Ruleinfo {
1699   XSolvable * const solvable;
1700   XSolvable * const othersolvable;
1701   %{
1702     SWIGINTERN XSolvable *Ruleinfo_solvable_get(Ruleinfo *ri) {
1703       return new_XSolvable(ri->solv->pool, ri->source);
1704     }
1705     SWIGINTERN XSolvable *Ruleinfo_othersolvable_get(Ruleinfo *ri) {
1706       return new_XSolvable(ri->solv->pool, ri->target);
1707     }
1708   %}
1709   const char *problemstr() {
1710     return solver_problemruleinfo2str($self->solv, $self->type, $self->source, $self->target, $self->dep);
1711   }
1712 }
1713
1714 %extend XRepodata {
1715   XRepodata(Repo *repo, Id id) {
1716     XRepodata *xr = sat_calloc(1, sizeof(*xr));
1717     xr->repo = repo;
1718     xr->id = id;
1719     return xr;
1720   }
1721   Id new_handle() {
1722     return repodata_new_handle($self->repo->repodata + $self->id);
1723   }
1724   void set_id(Id solvid, Id keyname, Id id) {
1725     repodata_set_id($self->repo->repodata + $self->id, solvid, keyname, id);
1726   }
1727   void set_str(Id solvid, Id keyname, const char *str) {
1728     repodata_set_str($self->repo->repodata + $self->id, solvid, keyname, str);
1729   }
1730   void set_poolstr(Id solvid, Id keyname, const char *str) {
1731     repodata_set_poolstr($self->repo->repodata + $self->id, solvid, keyname, str);
1732   }
1733   void add_idarray(Id solvid, Id keyname, Id id) {
1734     repodata_add_idarray($self->repo->repodata + $self->id, solvid, keyname, id);
1735   }
1736   void add_flexarray(Id solvid, Id keyname, Id handle) {
1737     repodata_add_flexarray($self->repo->repodata + $self->id, solvid, keyname, handle);
1738   }
1739   void set_bin_checksum(Id solvid, Id keyname, Chksum *chksum) {
1740     const unsigned char *buf = sat_chksum_get(chksum, 0);
1741     if (buf)
1742       repodata_set_bin_checksum($self->repo->repodata + $self->id, solvid, keyname, sat_chksum_get_type(chksum), buf);
1743   }
1744   const char *lookup_str(Id solvid, Id keyname) {
1745     return repodata_lookup_str($self->repo->repodata + $self->id, solvid, keyname);
1746   }
1747   Queue lookup_idarray(Id solvid, Id keyname) {
1748     Queue r;
1749     queue_init(&r);
1750     repodata_lookup_idarray($self->repo->repodata + $self->id, solvid, keyname, &r);
1751     return r;
1752   }
1753   %newobject lookup_checksum;
1754   Chksum *lookup_checksum(Id solvid, Id keyname) {
1755     Id type = 0;
1756     const unsigned char *b = repodata_lookup_bin_checksum($self->repo->repodata + $self->id, solvid, keyname, &type);
1757     return sat_chksum_create_from_bin(type, b);
1758   }
1759   void internalize() {
1760     repodata_internalize($self->repo->repodata + $self->id);
1761   }
1762   void create_stubs() {
1763     repodata_create_stubs($self->repo->repodata + $self->id);
1764   }
1765   void write(FILE *fp) {
1766     repodata_write($self->repo->repodata + $self->id, fp, repo_write_stdkeyfilter, 0);
1767   }
1768   bool read_solv_flags(FILE *fp, int flags = 0) {
1769     Repodata *data = $self->repo->repodata + $self->id;
1770     int r, oldstate = data->state;
1771     data->state = REPODATA_LOADING;
1772     r = repo_add_solv_flags(data->repo, fp, flags | REPO_USE_LOADING);
1773     if (r)
1774       data->state = oldstate;
1775     return r;
1776   }
1777   void extend_to_repo() {
1778     Repodata *data = $self->repo->repodata + $self->id;
1779     repodata_extend_block(data, data->repo->start, data->repo->end - data->repo->start);
1780   }
1781 }
1782