- fix some memory leaks
[platform/upstream/libsolv.git] / examples / solv.i
1 #
2 ##if defined(SWIGRUBY)
3 #  %rename("to_s") string();
4 ##endif
5 ##if defined(SWIGPYTHON)
6 #  %rename("__str__") string();
7 ##endif
8 #
9
10 %module solv
11
12 %typemap(in) (Id *idarray, int idarraylen) {
13   /* Check if is a list */
14   if (PyList_Check($input)) {
15     int size = PyList_Size($input);
16     int i = 0;
17     $1 = (Id *)sat_malloc2(size, sizeof(Id));
18     for (i = 0; i < size; i++) {
19       PyObject *o = PyList_GetItem($input,i);
20       int v;
21       int e = SWIG_AsVal_int(o, &v);
22       if (!SWIG_IsOK(e)) {
23         SWIG_exception_fail(SWIG_ArgError(e), "list must contain integers");
24         sat_free($1);
25         return NULL;
26       }
27       $1[i] = v;
28     }
29     $2 = size;
30   } else {
31     PyErr_SetString(PyExc_TypeError,"not a list");
32     return NULL;
33   }
34 }
35 %typemap(freearg) (Id *idarray, int idarraylen) {
36   sat_free($1);
37 }
38
39 %typemap(in) Queue {
40   /* Check if is a list */
41   queue_init(&$1);
42   if (PyList_Check($input)) {
43     int size = PyList_Size($input);
44     int i = 0;
45     for (i = 0; i < size; i++) {
46       PyObject *o = PyList_GetItem($input,i);
47       int v;
48       int e = SWIG_AsVal_int(o, &v);
49       if (!SWIG_IsOK(e)) {
50         SWIG_exception_fail(SWIG_ArgError(e), "list must contain only integers");
51         queue_free(&$1);
52         return NULL;
53       }
54       queue_push(&$1, v);
55     }
56   } else {
57     PyErr_SetString(PyExc_TypeError,"not a list");
58     return NULL;
59   }
60 }
61 %typemap(out) Queue {
62   int i;
63   PyObject *o = PyList_New($1.count);
64   for (i = 0; i < $1.count; i++)
65     PyList_SetItem(o, i, SWIG_From_int($1.elements[i]));
66   queue_free(&$1);
67   $result = o;
68 }
69 %typemap(arginit) Queue {
70   queue_init(&$1);
71 }
72 %typemap(freearg) Queue {
73   queue_free(&$1);
74 }
75
76
77 %include "cdata.i"
78 %include "file.i"
79 %include "typemaps.i"
80
81 %{
82 #include "stdio.h"
83 #include "pool.h"
84 #include "solver.h"
85 #include "repo_solv.h"
86 #include "chksum.h"
87
88 #include "repo_rpmdb.h"
89 #include "repo_rpmmd.h"
90 #include "repo_write.h"
91 #include "repo_products.h"
92 #include "repo_susetags.h"
93 #include "repo_updateinfoxml.h"
94 #include "repo_deltainfoxml.h"
95 #include "repo_repomdxml.h"
96 #include "repo_content.h"
97 #include "sat_xfopen.h"
98
99 #define true 1
100 #define false 1
101
102 #define SOLVER_SOLUTION_DEINSTALL -100
103 #define SOLVER_SOLUTION_REPLACE -101
104 typedef struct chksum Chksum;
105 typedef int bool;
106
107 typedef struct {
108   Pool* pool;
109   Id id;
110 } XSolvable;
111
112 typedef struct {
113   Solver* solv;
114   Id id;
115 } XRule;
116
117 typedef struct {
118   Repo* repo;
119   Id id;
120 } XRepodata;
121
122 typedef struct {
123   Pool *pool;
124   Id id;
125 } Pool_solvable_iterator;
126
127 typedef struct {
128   Pool *pool;
129   Id id;
130 } Pool_repo_iterator;
131
132 typedef struct {
133   Repo *repo;
134   Id id;
135 } Repo_solvable_iterator;
136
137 typedef struct {
138   Pool *pool;
139   Id how;
140   Id what;
141 } Job;
142
143 typedef struct {
144   Solver *solv;
145   Id id;
146 } Problem;
147
148 typedef struct {
149   Solver *solv;
150   Id problemid;
151   Id id;
152 } Solution;
153
154 typedef struct {
155   Solver *solv;
156   Id problemid;
157   Id solutionid;
158   Id id;
159
160   Id type;
161   Id p;
162   Id rp;
163 } Solutionelement;
164
165 %}
166
167 typedef int Id;
168
169 %include "knownid.h"
170
171 # from repodata.h
172 %constant Id SOLVID_META;
173 %constant Id SOLVID_POS;
174
175 %constant int REL_EQ;
176 %constant int REL_GT;
177 %constant int REL_LT;
178 %constant int REL_ARCH;
179
180
181 typedef struct {
182   Pool* const pool;
183   Id const id;
184 } XSolvable;
185
186 typedef struct {
187   Solver* const solv;
188   Id const id;
189 } XRule;
190
191 typedef struct {
192   Repo* const repo;
193   Id const id;
194 } XRepodata;
195
196 # put before pool/repo so we can access the constructor
197 %nodefaultctor Dataiterator;
198 %nodefaultdtor Dataiterator;
199 typedef struct _Dataiterator {
200   Pool * const pool;
201   Repo * const repo;
202   const Id solvid;
203 } Dataiterator;
204
205 typedef struct {
206   Pool * const pool;
207   Id how;
208   Id what;
209 } Job;
210
211 %nodefaultctor Pool;
212 %nodefaultdtor Pool;
213 typedef struct {
214 } Pool;
215
216 %nodefaultctor Repo;
217 %nodefaultdtor Repo;
218 typedef struct _Repo {
219   const char * const name;
220   int priority;
221   int subpriority;
222   int const nsolvables;
223 #if defined(SWIGRUBY)
224   VALUE appdata;
225 #endif
226 #if defined(SWIGPERL)
227   SV *appdata;
228 #endif
229 } Repo;
230
231 %nodefaultctor Pool_solvable_iterator;
232 typedef struct {} Pool_solvable_iterator;
233
234 %nodefaultctor Pool_repo_iterator;
235 typedef struct {} Pool_repo_iterator;
236
237 %nodefaultctor Repo_solvable_iterator;
238 typedef struct {} Repo_solvable_iterator;
239
240 %nodefaultctor Solver;
241 %nodefaultdtor Solver;
242 typedef struct {
243   Pool * const pool;
244   bool ignorealreadyrecommended;
245   bool dosplitprovides;
246   bool fixsystem;
247   bool allowuninstall;
248   bool distupgrade;
249   bool allowdowngrade;
250   bool allowarchchange;
251   bool allowvendorchange;
252 } Solver;
253
254 typedef struct chksum {} Chksum;
255
256 %rename(xfopen) sat_xfopen;
257 %rename(xfopen_fd) sat_xfopen_fd;
258 %rename(xfclose) sat_xfclose;
259 %rename(xfileno) sat_xfileno;
260
261 FILE *sat_xfopen(const char *fn);
262 FILE *sat_xfopen_fd(const char *fn, int fd);
263 %inline {
264   int sat_xfclose(FILE *fp) {
265     return fclose(fp);
266   }
267   int sat_xfileno(FILE *fp) {
268     return fileno(fp);
269   }
270 }
271
272 typedef struct {
273   Solver * const solv;
274   Id const id;
275 } Problem;
276
277 typedef struct {
278   Solver * const solv;
279   Id const problemid;
280   Id const id;
281 } Solution;
282
283 typedef struct {
284   Solver *const solv;
285   Id const problemid;
286   Id const solutionid;
287   Id const id;
288   Id const type;
289 } Solutionelement;
290
291 %nodefaultctor Transaction;
292 %nodefaultdtor Transaction;
293 typedef struct {
294   Pool * const pool;
295 } Transaction;
296
297
298
299 %extend Job {
300   static const Id SOLVER_SOLVABLE = SOLVER_SOLVABLE;
301   static const Id SOLVER_SOLVABLE_NAME = SOLVER_SOLVABLE_NAME;
302   static const Id SOLVER_SOLVABLE_PROVIDES = SOLVER_SOLVABLE_PROVIDES;
303   static const Id SOLVER_SOLVABLE_ONE_OF = SOLVER_SOLVABLE_ONE_OF;
304   static const Id SOLVER_SOLVABLE_REPO = SOLVER_SOLVABLE_REPO;
305   static const Id SOLVER_SOLVABLE_ALL = SOLVER_SOLVABLE_ALL;
306   static const Id SOLVER_SELECTMASK = SOLVER_SELECTMASK;
307   static const Id SOLVER_NOOP = SOLVER_NOOP;
308   static const Id SOLVER_INSTALL = SOLVER_INSTALL;
309   static const Id SOLVER_ERASE = SOLVER_ERASE;
310   static const Id SOLVER_UPDATE = SOLVER_UPDATE;
311   static const Id SOLVER_WEAKENDEPS = SOLVER_WEAKENDEPS;
312   static const Id SOLVER_NOOBSOLETES = SOLVER_NOOBSOLETES;
313   static const Id SOLVER_LOCK = SOLVER_LOCK;
314   static const Id SOLVER_DISTUPGRADE = SOLVER_DISTUPGRADE;
315   static const Id SOLVER_VERIFY = SOLVER_VERIFY;
316   static const Id SOLVER_DROP_ORPHANED = SOLVER_DROP_ORPHANED;
317   static const Id SOLVER_USERINSTALLED = SOLVER_USERINSTALLED;
318   static const Id SOLVER_JOBMASK = SOLVER_JOBMASK;
319   static const Id SOLVER_WEAK = SOLVER_WEAK;
320   static const Id SOLVER_ESSENTIAL = SOLVER_ESSENTIAL;
321   static const Id SOLVER_CLEANDEPS = SOLVER_CLEANDEPS;
322   static const Id SOLVER_SETEV = SOLVER_SETEV;
323   static const Id SOLVER_SETEVR = SOLVER_SETEVR;
324   static const Id SOLVER_SETARCH = SOLVER_SETARCH;
325   static const Id SOLVER_SETVENDOR = SOLVER_SETVENDOR;
326   static const Id SOLVER_SETREPO = SOLVER_SETREPO;
327   static const Id SOLVER_NOAUTOSET = SOLVER_NOAUTOSET;
328   static const Id SOLVER_SETMASK = SOLVER_SETMASK;
329
330   Job(Pool *pool, Id how, Id what) {
331     Job *job = sat_calloc(1, sizeof(*job));
332     job->pool = pool;
333     job->how = how;
334     job->what = what;
335     return job;
336   }
337 }
338
339 %extend Chksum {
340   Chksum(Id type) {
341     return (Chksum *)sat_chksum_create(type);
342   }
343   ~Chksum() {
344     sat_chksum_free($self, 0);
345   }
346   void add(const char *str) {
347     sat_chksum_add($self, str, strlen((char *)str));
348   }
349   void addfp(FILE *fp) {
350     char buf[4096];
351     int l;
352     while ((l = fread(buf, 1, sizeof(buf), fp)) > 0)
353       sat_chksum_add($self, buf, l);
354     rewind(fp);         /* convenience */
355   }
356   void addfd(int fd) {
357     char buf[4096];
358     int l;
359     while ((l = read(fd, buf, sizeof(buf))) > 0)
360       sat_chksum_add($self, buf, l);
361     lseek(fd, 0, 0);    /* convenience */
362   }
363   bool matches(char *othersum) {
364     int l;
365     unsigned char *b;
366     b = sat_chksum_get($self, &l);
367     return memcmp(b, (void *)othersum, l) == 0;
368   }
369   SWIGCDATA raw() {
370     int l;
371     unsigned char *b;
372     b = sat_chksum_get($self, &l);
373     return cdata_void((void *)b, l);
374   }
375 }
376
377
378
379 %extend Pool {
380   Pool() {
381     Pool *pool = pool_create();
382     return pool;
383   }
384   ~Pool() {
385   }
386   void set_debuglevel(int level) {
387     pool_setdebuglevel($self, level);
388   }
389 #if defined(SWIGPYTHON)
390   %{
391   SWIGINTERN int loadcallback(Pool *pool, Repodata *data, void *d) {
392     XRepodata *xd = new_XRepodata(data->repo, data - data->repo->repodata);
393     PyObject *args = Py_BuildValue("(O)", SWIG_NewPointerObj(SWIG_as_voidptr(xd), SWIGTYPE_p_XRepodata, SWIG_POINTER_OWN | 0));
394     PyObject *result = PyEval_CallObject((PyObject *)d, args);
395     if (!result)
396       return 0; /* exception */
397     int ecode = 0;
398     int vresult = 0;
399     Py_DECREF(args);
400     ecode = SWIG_AsVal_int(result, &vresult);
401     Py_DECREF(result);
402     return SWIG_IsOK(ecode) ? vresult : 0;
403   }
404   %}
405   void set_loadcallback(PyObject *callable) {
406     if (!callable) {
407       if ($self->loadcallback == loadcallback) {
408         Py_DECREF($self->loadcallbackdata);
409         pool_setloadcallback($self, 0, 0);
410       }
411       return;
412     }
413     Py_INCREF(callable);
414     pool_setloadcallback($self, loadcallback, callable);
415   }
416 #endif
417   void free() {
418 #if defined(SWIGPYTHON)
419     Pool_set_loadcallback($self, 0);
420 #endif
421     pool_free($self);
422   }
423   Id str2id(const char *str, int create=1) {
424     return str2id($self, str, create);
425   }
426   const char *id2str(Id id) {
427     return id2str($self, id);
428   }
429   const char *dep2str(Id id) {
430     return dep2str($self, id);
431   }
432   Id rel2id(Id name, Id evr, int flags, int create=1) {
433     return rel2id($self, name, evr, flags, create);
434   }
435   void setarch(const char *arch) {
436     pool_setarch($self, arch);
437   }
438   Repo *add_repo(const char *name) {
439     return repo_create($self, name);
440   }
441   const char *lookup_str(Id entry, Id keyname) {
442     return pool_lookup_str($self, entry, keyname);
443   }
444   Id lookup_id(Id entry, Id keyname) {
445     return pool_lookup_id($self, entry, keyname);
446   }
447   unsigned int lookup_num(Id entry, Id keyname, unsigned int notfound = 0) {
448     return pool_lookup_num($self, entry, keyname, notfound);
449   }
450   bool lookup_void(Id entry, Id keyname) {
451     return pool_lookup_void($self, entry, keyname);
452   }
453   SWIGCDATA lookup_bin_checksum(Id entry, Id keyname, Id *OUTPUT) {
454     int l;
455     const unsigned char *b;
456     *OUTPUT = 0;
457     b = pool_lookup_bin_checksum($self, entry, keyname, OUTPUT);
458     if (!b)
459       return cdata_void(0, 0);
460     return cdata_void((char *)b, sat_chksum_len(*OUTPUT));
461   }
462   const char *lookup_checksum(Id entry, Id keyname, Id *OUTPUT) {
463     Id type = 0;
464     *OUTPUT = 0;
465     const char *b = pool_lookup_checksum($self, entry, keyname, OUTPUT);
466     return b;
467   }
468   %newobject dataiterator_new;
469   Dataiterator *dataiterator_new(Id p, Id key,  const char *match, int flags) {
470     return new_Dataiterator($self, 0, p, key, match, flags);
471   }
472   const char *solvid2str(Id solvid) {
473     return solvid2str($self, solvid);
474   }
475   void addfileprovides() {
476     pool_addfileprovides($self);
477   }
478   void createwhatprovides() {
479     pool_createwhatprovides($self);
480   }
481   %newobject solvables;
482   Pool_solvable_iterator * const solvables;
483   %{
484   SWIGINTERN Pool_solvable_iterator * Pool_solvables_get(Pool *pool) {
485     Pool_solvable_iterator *s;
486     s = sat_calloc(1, sizeof(*s));
487     s->pool = pool;
488     s->id = 0;
489     return s;
490   }
491   %}
492   %newobject repos;
493   Pool_repo_iterator * const repos;
494   %{
495   SWIGINTERN Pool_repo_iterator * Pool_repos_get(Pool *pool) {
496     Pool_repo_iterator *s;
497     s = sat_calloc(1, sizeof(*s));
498     s->pool = pool;
499     s->id = 0;
500     return s;
501   }
502   %}
503   Repo *installed;
504   %{
505   SWIGINTERN void Pool_installed_set(Pool *pool, Repo *installed) {
506     pool_set_installed(pool, installed);
507   }
508   Repo *Pool_installed_get(Pool *pool) {
509     return pool->installed;
510   }
511   %}
512
513   Queue providerids(Id dep) {
514     Pool *pool = $self;
515     Queue q;
516     Id p, pp;
517     queue_init(&q);
518     FOR_PROVIDES(p, pp, dep)
519       queue_push(&q, p);
520     return q;
521   }
522   Queue allprovidingids() {
523     Pool *pool = $self;
524     Queue q;
525     Id id;
526     queue_init(&q);
527     for (id = 1; id < pool->ss.nstrings; id++)
528       if (pool->whatprovides[id])
529         queue_push(&q, id);
530     return q;
531   }
532   # move to job?
533   Queue jobsolvids(Job *job) {
534     Pool *pool = $self;
535     Id p, pp, how;
536     Queue q;
537     queue_init(&q);
538     how = job->how & SOLVER_SELECTMASK;
539     FOR_JOB_SELECT(p, pp, how, job->what)
540       queue_push(&q, p);
541     return q;
542   }
543   Job *Job(Id how, Id what) {
544     return new_Job($self, how, what);
545   }
546
547 #if defined(SWIGPYTHON)
548   %pythoncode {
549     def jobsolvables (self, *args):
550       return [ self.solvables[id] for id in self.jobsolvids(*args) ]
551     def providers(self, *args):
552       return [ self.solvables[id] for id in self.providerids(*args) ]
553   }
554 #endif
555
556   Id towhatprovides(Queue q) {
557     return pool_queuetowhatprovides($self, &q);
558   }
559   bool isknownarch(Id id) {
560     Pool *pool = $self;
561     if (id == ARCH_SRC || id == ARCH_NOSRC || id == ARCH_NOARCH)
562       return 1;
563     if (pool->id2arch && (id > pool->lastarch || !pool->id2arch[id]))
564       return 0;
565     return 1;
566   }
567
568   %newobject create_solver;
569   Solver *create_solver() {
570     return solver_create($self);
571   }
572 }
573
574 %extend Repo {
575   static const int REPO_REUSE_REPODATA = REPO_REUSE_REPODATA;
576   static const int REPO_NO_INTERNALIZE = REPO_NO_INTERNALIZE;
577   static const int REPO_LOCALPOOL = REPO_LOCALPOOL;
578   static const int REPO_USE_LOADING = REPO_USE_LOADING;
579   static const int REPO_EXTEND_SOLVABLES = REPO_EXTEND_SOLVABLES;
580   static const int SOLV_ADD_NO_STUBS = SOLV_ADD_NO_STUBS;       /* repo_solv */
581   static const int SUSETAGS_RECORD_SHARES = SUSETAGS_RECORD_SHARES; /* repo_susetags */
582
583   void free(int reuseids = 0) {
584     repo_free($self, reuseids);
585   }
586   bool add_solv(const char *name, int flags = 0) {
587     FILE *fp = fopen(name, "r");
588     if (!fp)
589       return 0;
590     int r = repo_add_solv_flags($self, fp, flags);
591     fclose(fp);
592     return r == 0;
593   }
594   bool add_solv(FILE *fp, int flags = 0) {
595     return repo_add_solv_flags($self, fp, flags) == 0;
596   }
597   bool add_products(const char *proddir, int flags = 0) {
598     repo_add_products($self, proddir, 0, flags);
599     return 1;
600   }
601   bool add_rpmmd(FILE *fp, const char *language, int flags = 0) {
602     repo_add_rpmmd($self, fp, language, flags);
603     return 1;
604   }
605   bool add_rpmdb(Repo *ref, int flags = 0) {
606     repo_add_rpmdb($self, ref, 0, flags);
607     return 1;
608   }
609   bool add_susetags(FILE *fp, Id defvendor, const char *language, int flags = 0) {
610     repo_add_susetags($self, fp, defvendor, language, flags);
611     return 1;
612   }
613   bool add_repomdxml(FILE *fp, int flags = 0) {
614     repo_add_repomdxml($self, fp, flags);
615     return 1;
616   }
617   bool add_content(FILE *fp, int flags = 0) {
618     repo_add_content($self, fp, flags);
619     return 1;
620   }
621   bool add_updateinfoxml(FILE *fp, int flags = 0) {
622     repo_add_updateinfoxml($self, fp, flags);
623     return 1;
624   }
625   bool add_deltainfoxml(FILE *fp, int flags = 0) {
626     repo_add_deltainfoxml($self, fp, flags);
627     return 1;
628   }
629   void internalize() {
630     repo_internalize($self);
631   }
632   const char *lookup_str(Id entry, Id keyname) {
633     return repo_lookup_str($self, entry, keyname);
634   }
635   Id lookup_id(Id entry, Id keyname) {
636     return repo_lookup_id($self, entry, keyname);
637   }
638   unsigned int lookup_num(Id entry, Id keyname, unsigned int notfound = 0) {
639     return repo_lookup_num($self, entry, keyname, notfound);
640   }
641   void write(FILE *fp) {
642     repo_write($self, fp, repo_write_stdkeyfilter, 0, 0);
643   }
644   # HACK, remove if no longer needed!
645   bool write_first_repodata(FILE *fp, int flags = 0) {
646     int oldnrepodata = $self->nrepodata;
647     $self->nrepodata = 1;
648     repo_write($self, fp, repo_write_stdkeyfilter, 0, 0);
649     $self->nrepodata = oldnrepodata;
650     return 1;
651   }
652   %newobject dataiterator_new;
653   Dataiterator *dataiterator_new(Id p, Id key,  const char *match, int flags) {
654     return new_Dataiterator($self->pool, $self, p, key, match, flags);
655   }
656
657   Id const id;
658   %{
659   SWIGINTERN Id Repo_id_get(Repo *repo) {
660     return repo->repoid;
661   }
662   %}
663   Repo_solvable_iterator * const solvables;
664   %{
665   SWIGINTERN Repo_solvable_iterator * Repo_solvables_get(Repo *repo) {
666     Repo_solvable_iterator *s;
667     s = sat_calloc(1, sizeof(*s));
668     s->repo = repo;
669     s->id = 0;
670     return s;
671   }
672   %}
673
674   XRepodata *add_repodata(int flags = 0) {
675     Repodata *rd = repo_add_repodata($self, flags);
676     return new_XRepodata($self, rd - $self->repodata);
677   }
678
679   void create_stubs() {
680     Repodata *data;
681     if (!$self->nrepodata)
682       return;
683     data = $self->repodata  + ($self->nrepodata - 1);
684     if (data->state != REPODATA_STUB)
685       repodata_create_stubs(data);
686   }
687 #if defined(SWIGPYTHON)
688   PyObject *appdata;
689   %{
690   SWIGINTERN void Repo_appdata_set(Repo *repo, PyObject *o) {
691     repo->appdata = o;
692   }
693   SWIGINTERN PyObject *Repo_appdata_get(Repo *repo) {
694     PyObject *o = repo->appdata;
695     Py_INCREF(o);
696     return o;
697   }
698   %}
699 #endif
700 }
701
702 %extend Dataiterator {
703   static const int SEARCH_STRING = SEARCH_STRING;
704   static const int SEARCH_SUBSTRING = SEARCH_SUBSTRING;
705   static const int SEARCH_GLOB = SEARCH_GLOB;
706   static const int SEARCH_REGEX = SEARCH_REGEX;
707   static const int SEARCH_NOCASE = SEARCH_NOCASE;
708   static const int SEARCH_FILES = SEARCH_FILES;
709   static const int SEARCH_COMPLETE_FILELIST = SEARCH_COMPLETE_FILELIST;
710
711   Dataiterator(Pool *pool, Repo *repo, Id p, Id key, const char *match, int flags) {
712     Dataiterator *di = sat_calloc(1, sizeof(*di));
713     dataiterator_init(di, pool, repo, p, key, match, flags);
714     return di;
715   }
716   ~Dataiterator() {
717     dataiterator_free($self);
718     sat_free($self);
719   }
720   Dataiterator *__iter__() {
721     return $self;
722   }
723   %exception next {
724     $action
725     if (!result) {
726       PyErr_SetString(PyExc_StopIteration,"no more matches");
727       return NULL;
728     }
729   }
730   %newobject next;
731   Dataiterator *next() {
732     Dataiterator *ndi;
733     if (!dataiterator_step($self)) {
734       return 0;
735     }
736     ndi = sat_calloc(1, sizeof(*ndi));
737     dataiterator_init_clone(ndi, $self);
738     return ndi;
739   }
740   void setpos_parent() {
741     dataiterator_setpos_parent($self);
742   }
743   void prepend_keyname(Id key) {
744     dataiterator_prepend_keyname($self, key);
745   }
746   void skip_solvable() {
747     dataiterator_skip_solvable($self);
748   }
749
750   %newobject solvable;
751   XSolvable * const solvable;
752   %{
753   SWIGINTERN XSolvable *Dataiterator_solvable_get(Dataiterator *di) {
754     return new_XSolvable(di->pool, di->solvid);
755   }
756   %}
757   Id key_id() {
758     return $self->key->name;
759   }
760   const char *key_idstr() {
761     return id2str($self->pool, $self->key->name);
762   }
763   Id keytype_id() {
764     return $self->key->type;
765   }
766   const char *keytype_idstr() {
767     return id2str($self->pool, $self->key->type);
768   }
769   Id match_id() {
770      return $self->kv.id;
771   }
772   const char *match_idstr() {
773      return id2str($self->pool, $self->kv.id);
774   }
775   const char *match_str() {
776      return $self->kv.str;
777   }
778   int match_num() {
779      return $self->kv.num;
780   }
781   int match_num2() {
782      return $self->kv.num2;
783   }
784 }
785
786
787 %extend Pool_solvable_iterator {
788   Pool_solvable_iterator *__iter__() {
789     return $self;
790   }
791   %exception next {
792     $action
793     if (!result) {
794       PyErr_SetString(PyExc_StopIteration,"no more matches");
795       return NULL;
796     }
797   }
798   %newobject next;
799   XSolvable *next() {
800     Pool *pool = $self->pool;
801     XSolvable *s;
802     if ($self->id >= pool->nsolvables)
803       return 0;
804     while (++$self->id < pool->nsolvables)
805       if (pool->solvables[$self->id].repo)
806         return new_XSolvable(pool, $self->id);
807     return 0;
808   }
809   %newobject __getitem__;
810   XSolvable *__getitem__(Id key) {
811     Pool *pool = $self->pool;
812     if (key > 0 && key < pool->nsolvables && pool->solvables[key].repo)
813       return new_XSolvable(pool, key);
814     return 0;
815   }
816 }
817
818 %extend Pool_repo_iterator {
819   Pool_repo_iterator *__iter__() {
820     return $self;
821   }
822   %exception next {
823     $action
824     if (!result) {
825       PyErr_SetString(PyExc_StopIteration,"no more matches");
826       return NULL;
827     }
828   }
829   Repo *next() {
830     Pool *pool = $self->pool;
831     if ($self->id >= pool->nrepos + 1)
832       return 0;
833     while (++$self->id < pool->nrepos + 1) {
834       Repo *r = pool_id2repo(pool, $self->id);
835       if (r)
836         return r;
837     }
838     return 0;
839   }
840   Repo *__getitem__(Id key) {
841     Pool *pool = $self->pool;
842     if (key > 0 && key < pool->nrepos + 1)
843       return pool_id2repo(pool, key);
844     return 0;
845   }
846 }
847
848 %extend Repo_solvable_iterator {
849   Repo_solvable_iterator *__iter__() {
850     return $self;
851   }
852   %exception next {
853     $action
854     if (!result) {
855       PyErr_SetString(PyExc_StopIteration,"no more matches");
856       return NULL;
857     }
858   }
859   %newobject next;
860   XSolvable *next() {
861     Repo *repo = $self->repo;
862     Pool *pool = repo->pool;
863     XSolvable *s;
864     if (repo->start > 0 && $self->id < repo->start)
865       $self->id = repo->start - 1;
866     if ($self->id >= repo->end)
867       return 0;
868     while (++$self->id < repo->end)
869       if (pool->solvables[$self->id].repo == repo)
870         return new_XSolvable(pool, $self->id);
871     return 0;
872   }
873   %newobject __getitem__;
874   XSolvable *__getitem__(Id key) {
875     Repo *repo = $self->repo;
876     Pool *pool = repo->pool;
877     if (key > 0 && key < pool->nsolvables && pool->solvables[key].repo == repo)
878       return new_XSolvable(pool, key);
879     return 0;
880   }
881 }
882
883 %extend XSolvable {
884   XSolvable(Pool *pool, Id id) {
885     if (!id)
886       return 0;
887     XSolvable *s = sat_calloc(1, sizeof(*s));
888     s->pool = pool;
889     s->id = id;
890     return s;
891   }
892   const char *str() {
893     return solvid2str($self->pool, $self->id);
894   }
895   const char *lookup_str(Id keyname) {
896     return pool_lookup_str($self->pool, $self->id, keyname);
897   }
898   Id lookup_id(Id keyname) {
899     return pool_lookup_id($self->pool, $self->id, keyname);
900   }
901   unsigned int lookup_num(Id keyname, unsigned int notfound = 0) {
902     return pool_lookup_num($self->pool, $self->id, keyname, notfound);
903   }
904   bool lookup_void(Id keyname) {
905     return pool_lookup_void($self->pool, $self->id, keyname);
906   }
907   SWIGCDATA lookup_bin_checksum(Id keyname, Id *OUTPUT) {
908     int l;
909     const unsigned char *b;
910     *OUTPUT = 0;
911     b = pool_lookup_bin_checksum($self->pool, $self->id, keyname, OUTPUT);
912     if (!b)
913       return cdata_void(0, 0);
914     return cdata_void((char *)b, sat_chksum_len(*OUTPUT));
915   }
916   const char *lookup_checksum(Id keyname, Id *OUTPUT) {
917     Id type = 0;
918     *OUTPUT = 0;
919     const char *b = pool_lookup_checksum($self->pool, $self->id, keyname, OUTPUT);
920     return b;
921   }
922   const char *lookup_location(int *OUTPUT) {
923     return solvable_get_location($self->pool->solvables + $self->id, OUTPUT);
924   }
925   bool installable() {
926     return pool_installable($self->pool, pool_id2solvable($self->pool, $self->id));
927   }
928   bool isinstalled() {
929     Pool *pool = $self->pool;
930     return pool->installed && pool_id2solvable(pool, $self->id)->repo == pool->installed;
931   }
932
933   const char * const name;
934   %{
935     SWIGINTERN const char *XSolvable_name_get(XSolvable *xs) {
936       Pool *pool = xs->pool;
937       return id2str(pool, pool->solvables[xs->id].name);
938     }
939   %}
940   Id const nameid;
941   %{
942     SWIGINTERN Id XSolvable_nameid_get(XSolvable *xs) {
943       return xs->pool->solvables[xs->id].name;
944     }
945   %}
946   const char * const evr;
947   %{
948     SWIGINTERN const char *XSolvable_evr_get(XSolvable *xs) {
949       Pool *pool = xs->pool;
950       return id2str(pool, pool->solvables[xs->id].evr);
951     }
952   %}
953   Id const evrid;
954   %{
955     SWIGINTERN Id XSolvable_evrid_get(XSolvable *xs) {
956       return xs->pool->solvables[xs->id].evr;
957     }
958   %}
959   const char * const arch;
960   %{
961     SWIGINTERN const char *XSolvable_arch_get(XSolvable *xs) {
962       Pool *pool = xs->pool;
963       return id2str(pool, pool->solvables[xs->id].arch);
964     }
965   %}
966   Id const archid;
967   %{
968     SWIGINTERN Id XSolvable_archid_get(XSolvable *xs) {
969       return xs->pool->solvables[xs->id].arch;
970     }
971   %}
972   Repo * const repo;
973   %{
974     SWIGINTERN Repo *XSolvable_repo_get(XSolvable *xs) {
975       return xs->pool->solvables[xs->id].repo;
976     }
977   %}
978 }
979
980 %extend Problem {
981   Problem(Solver *solv, Id id) {
982     Problem *p;
983     p = sat_calloc(1, sizeof(*p));
984     p->solv = solv;
985     p->id = id;
986     return p;
987   }
988   Id findproblemrule_helper() {
989     return solver_findproblemrule($self->solv, $self->id);
990   }
991   Queue findallproblemrules_helper(int unfiltered=0) {
992     Solver *solv = $self->solv;
993     Id probr;
994     int i, j;
995     Queue q;
996     queue_init(&q);
997     solver_findallproblemrules(solv, $self->id, &q);
998     if (!unfiltered)
999       {
1000         for (i = j = 0; i < q.count; i++)
1001           {
1002             probr = q.elements[i];
1003             if ((probr >= solv->updaterules && probr < solv->updaterules_end) || (probr >= solv->jobrules && probr < solv->jobrules_end))
1004               continue;
1005             q.elements[j++] = probr;
1006           }
1007         if (j)
1008           queue_truncate(&q, j);
1009       }
1010     return q;
1011   }
1012   int solution_count() {
1013     return solver_solution_count($self->solv, $self->id);
1014   }
1015 #if defined(SWIGPYTHON)
1016   %pythoncode {
1017     def findproblemrule(self):
1018       return XRule(self.solv, self.findproblemrule_helper())
1019     def findallproblemrules(self, unfiltered=0):
1020       return [ XRule(self.solv, i) for i in self.findallproblemrules_helper(unfiltered) ]
1021     def solutions(self):
1022       return [ Solution(self, i) for i in range(1, self.solution_count() + 1) ];
1023   }
1024 #endif
1025 }
1026
1027 %extend Solution {
1028   Solution(Problem *p, Id id) {
1029     Solution *s;
1030     s = sat_calloc(1, sizeof(*s));
1031     s->solv = p->solv;
1032     s->problemid = p->id;
1033     s->id = id;
1034     return s;
1035   }
1036   int element_count() {
1037     return solver_solutionelement_count($self->solv, $self->problemid, $self->id);
1038   }
1039 #if defined(SWIGPYTHON)
1040   %pythoncode {
1041     def elements(self):
1042       return [ Solutionelement(self, i) for i in range(1, self.element_count() + 1) ];
1043   }
1044 #endif
1045 }
1046
1047 %extend Solutionelement {
1048   Solutionelement(Solution *s, Id id) {
1049     Solutionelement *e;
1050     e = sat_calloc(1, sizeof(*e));
1051     e->solv = s->solv;
1052     e->problemid = s->problemid;
1053     e->solutionid = s->id;
1054     e->id = id;
1055     solver_next_solutionelement(e->solv, e->problemid, e->solutionid, e->id - 1, &e->p, &e->rp);
1056     if (e->p > 0) {
1057       e->type = e->rp ? SOLVER_SOLUTION_REPLACE : SOLVER_SOLUTION_DEINSTALL;
1058     } else {
1059       e->type = e->p;
1060       e->p = e->rp;
1061       e->rp = 0;
1062     }
1063     return e;
1064   }
1065   %newobject solvable;
1066   XSolvable * const solvable;
1067   %newobject replacement;
1068   XSolvable * const replacement;
1069   int const jobidx;
1070   %{
1071     SWIGINTERN XSolvable *Solutionelement_solvable_get(Solutionelement *e) {
1072       return new_XSolvable(e->solv->pool, e->p);
1073     }
1074     SWIGINTERN XSolvable *Solutionelement_replacement_get(Solutionelement *e) {
1075       return new_XSolvable(e->solv->pool, e->rp);
1076     }
1077     SWIGINTERN int Solutionelement_jobidx_get(Solutionelement *e) {
1078       return (e->p - 1) / 2;
1079     }
1080   %}
1081 }
1082
1083 %extend Solver {
1084   static const int SOLVER_RULE_UNKNOWN = SOLVER_RULE_UNKNOWN;
1085   static const int SOLVER_RULE_RPM = SOLVER_RULE_RPM;
1086   static const int SOLVER_RULE_RPM_NOT_INSTALLABLE = SOLVER_RULE_RPM_NOT_INSTALLABLE;
1087   static const int SOLVER_RULE_RPM_NOTHING_PROVIDES_DEP = SOLVER_RULE_RPM_NOTHING_PROVIDES_DEP;
1088   static const int SOLVER_RULE_RPM_PACKAGE_REQUIRES = SOLVER_RULE_RPM_PACKAGE_REQUIRES;
1089   static const int SOLVER_RULE_RPM_SELF_CONFLICT = SOLVER_RULE_RPM_SELF_CONFLICT;
1090   static const int SOLVER_RULE_RPM_PACKAGE_CONFLICT = SOLVER_RULE_RPM_PACKAGE_CONFLICT;
1091   static const int SOLVER_RULE_RPM_SAME_NAME = SOLVER_RULE_RPM_SAME_NAME;
1092   static const int SOLVER_RULE_RPM_PACKAGE_OBSOLETES = SOLVER_RULE_RPM_PACKAGE_OBSOLETES;
1093   static const int SOLVER_RULE_RPM_IMPLICIT_OBSOLETES = SOLVER_RULE_RPM_IMPLICIT_OBSOLETES;
1094   static const int SOLVER_RULE_RPM_INSTALLEDPKG_OBSOLETES = SOLVER_RULE_RPM_INSTALLEDPKG_OBSOLETES;
1095   static const int SOLVER_RULE_UPDATE = SOLVER_RULE_UPDATE;
1096   static const int SOLVER_RULE_FEATURE = SOLVER_RULE_FEATURE;
1097   static const int SOLVER_RULE_JOB = SOLVER_RULE_JOB;
1098   static const int SOLVER_RULE_JOB_NOTHING_PROVIDES_DEP = SOLVER_RULE_JOB_NOTHING_PROVIDES_DEP;
1099   static const int SOLVER_RULE_DISTUPGRADE = SOLVER_RULE_DISTUPGRADE;
1100   static const int SOLVER_RULE_INFARCH = SOLVER_RULE_INFARCH;
1101   static const int SOLVER_RULE_CHOICE = SOLVER_RULE_CHOICE;
1102   static const int SOLVER_RULE_LEARNT = SOLVER_RULE_LEARNT;
1103
1104   static const int SOLVER_SOLUTION_JOB = SOLVER_SOLUTION_JOB;
1105   static const int SOLVER_SOLUTION_INFARCH = SOLVER_SOLUTION_INFARCH;
1106   static const int SOLVER_SOLUTION_DISTUPGRADE = SOLVER_SOLUTION_DISTUPGRADE;
1107   static const int SOLVER_SOLUTION_DEINSTALL = SOLVER_SOLUTION_DEINSTALL;
1108   static const int SOLVER_SOLUTION_REPLACE = SOLVER_SOLUTION_REPLACE;
1109
1110   ~Solver() {
1111     solver_free($self);
1112   }
1113 #if defined(SWIGPYTHON)
1114   %pythoncode {
1115     def solve(self, jobs):
1116       j = []
1117       for job in jobs: j += [job.how, job.what]
1118       nprob = self.solve_helper(j)
1119       return [ Problem(self, pid) for pid in range(1, nprob + 1) ]
1120   }
1121 #endif
1122   int solve_helper(Queue jobs) {
1123     solver_solve($self, &jobs);
1124     return solver_problem_count($self);
1125   }
1126   %newobject transaction;
1127   Transaction *transaction() {
1128     Transaction *t;
1129     t = sat_calloc(1, sizeof(*t));
1130     transaction_init_clone(t, &$self->trans);
1131     return t;
1132   }
1133 }
1134
1135 %extend Transaction {
1136   static const int SOLVER_TRANSACTION_IGNORE = SOLVER_TRANSACTION_IGNORE;
1137   static const int SOLVER_TRANSACTION_ERASE = SOLVER_TRANSACTION_ERASE;
1138   static const int SOLVER_TRANSACTION_REINSTALLED = SOLVER_TRANSACTION_REINSTALLED;
1139   static const int SOLVER_TRANSACTION_DOWNGRADED = SOLVER_TRANSACTION_DOWNGRADED;
1140   static const int SOLVER_TRANSACTION_CHANGED = SOLVER_TRANSACTION_CHANGED;
1141   static const int SOLVER_TRANSACTION_UPGRADED = SOLVER_TRANSACTION_UPGRADED;
1142   static const int SOLVER_TRANSACTION_OBSOLETED = SOLVER_TRANSACTION_OBSOLETED;
1143   static const int SOLVER_TRANSACTION_INSTALL = SOLVER_TRANSACTION_INSTALL;
1144   static const int SOLVER_TRANSACTION_REINSTALL = SOLVER_TRANSACTION_REINSTALL;
1145   static const int SOLVER_TRANSACTION_DOWNGRADE = SOLVER_TRANSACTION_DOWNGRADE;
1146   static const int SOLVER_TRANSACTION_CHANGE = SOLVER_TRANSACTION_CHANGE;
1147   static const int SOLVER_TRANSACTION_UPGRADE = SOLVER_TRANSACTION_UPGRADE;
1148   static const int SOLVER_TRANSACTION_OBSOLETES = SOLVER_TRANSACTION_OBSOLETES;
1149   static const int SOLVER_TRANSACTION_MULTIINSTALL = SOLVER_TRANSACTION_MULTIINSTALL;
1150   static const int SOLVER_TRANSACTION_MULTIREINSTALL = SOLVER_TRANSACTION_MULTIREINSTALL;
1151   static const int SOLVER_TRANSACTION_MAXTYPE = SOLVER_TRANSACTION_MAXTYPE;
1152   static const int SOLVER_TRANSACTION_SHOW_ACTIVE = SOLVER_TRANSACTION_SHOW_ACTIVE;
1153   static const int SOLVER_TRANSACTION_SHOW_ALL = SOLVER_TRANSACTION_SHOW_ALL;
1154   static const int SOLVER_TRANSACTION_SHOW_OBSOLETES = SOLVER_TRANSACTION_SHOW_OBSOLETES;
1155   static const int SOLVER_TRANSACTION_SHOW_MULTIINSTALL = SOLVER_TRANSACTION_SHOW_MULTIINSTALL;
1156   static const int SOLVER_TRANSACTION_CHANGE_IS_REINSTALL = SOLVER_TRANSACTION_CHANGE_IS_REINSTALL;
1157   static const int SOLVER_TRANSACTION_MERGE_VENDORCHANGES = SOLVER_TRANSACTION_MERGE_VENDORCHANGES;
1158   static const int SOLVER_TRANSACTION_MERGE_ARCHCHANGES = SOLVER_TRANSACTION_MERGE_ARCHCHANGES;
1159   static const int SOLVER_TRANSACTION_RPM_ONLY = SOLVER_TRANSACTION_RPM_ONLY;
1160   static const int SOLVER_TRANSACTION_ARCHCHANGE = SOLVER_TRANSACTION_ARCHCHANGE;
1161   static const int SOLVER_TRANSACTION_VENDORCHANGE = SOLVER_TRANSACTION_VENDORCHANGE;
1162   static const int SOLVER_TRANSACTION_KEEP_ORDERDATA = SOLVER_TRANSACTION_KEEP_ORDERDATA;
1163   ~Transaction() {
1164     transaction_free($self);
1165     sat_free($self);
1166   }
1167   bool isempty() {
1168     return $self->steps.count == 0;
1169   }
1170   Queue classify_helper(int mode) {
1171     Queue q;
1172     queue_init(&q);
1173     transaction_classify($self, mode, &q);
1174     return q;
1175   }
1176   Queue classify_pkgs_helper(int mode, Id cl, Id from, Id to) {
1177     Queue q;
1178     queue_init(&q);
1179     transaction_classify_pkgs($self, mode, cl, from, to, &q);
1180     return q;
1181   }
1182   %newobject othersolvable;
1183   XSolvable *othersolvable(XSolvable *s) {
1184     Id op = transaction_obs_pkg($self, s->id);
1185     return new_XSolvable($self->pool, op);
1186   }
1187 #if defined(SWIGPYTHON)
1188   %pythoncode {
1189     def classify(self, mode = 0):
1190       r = []
1191       cr = self.classify_helper(mode)
1192       for type, cnt, fromid, toid in zip(*([iter(cr)] * 4)):
1193         if type != self.SOLVER_TRANSACTION_IGNORE:
1194           r.append([ type, [ self.pool.solvables[j] for j in self.classify_pkgs_helper(mode, type, fromid, toid) ], fromid, toid ])
1195       return r
1196     }
1197 #endif
1198   Queue installedresult_helper(int *OUTPUT) {
1199     Queue q;
1200     queue_init(&q);
1201     *OUTPUT = transaction_installedresult(self, &q);
1202     return q;
1203   }
1204 #if defined(SWIGPYTHON)
1205   %pythoncode {
1206     def installedresult(self):
1207       r = self.installedresult_helper()
1208       newpkgs = r.pop()
1209       rn = [ self.pool.solvables[r[i]] for i in range(0, newpkgs) ]
1210       rk = [ self.pool.solvables[r[i]] for i in range(newpkgs, len(r)) ]
1211       return rn, rk
1212   }
1213 #endif
1214   Queue steps_helper() {
1215     Queue q;
1216     queue_init_clone(&q, &$self->steps);
1217     return q;
1218   }
1219   int steptype(XSolvable *s, int mode) {
1220     return transaction_type($self, s->id, mode);
1221   }
1222 #if defined(SWIGPYTHON)
1223   %pythoncode {
1224     def steps(self):
1225       return [ self.pool.solvables[i] for i in self.steps_helper() ]
1226   }
1227 #endif
1228   int calc_installsizechange() {
1229     return transaction_calc_installsizechange($self);
1230   }
1231 }
1232
1233 %extend XRule {
1234   XRule(Solver *solv, Id id) {
1235     if (!id)
1236       return 0;
1237     XRule *xr = sat_calloc(1, sizeof(*xr));
1238     xr->solv = solv;
1239     xr->id = id;
1240     return xr;
1241   }
1242   %apply Id *OUTPUT { Id *source, Id *target, Id *dep };
1243   int info_helper(Id *source, Id *target, Id *dep) {
1244     return solver_ruleinfo($self->solv, $self->id, source, target, dep);
1245   }
1246 #if defined(SWIGPYTHON)
1247   %pythoncode {
1248     def info(self):
1249       type, source, target, dep = self.info_helper()
1250       if source:
1251           source = self.solv.pool.solvables[source]
1252       if target:
1253           target = self.solv.pool.solvables[target]
1254       return type, source, target, dep
1255   }
1256 #endif
1257 }
1258
1259
1260 %extend XRepodata {
1261   XRepodata(Repo *repo, Id id) {
1262     XRepodata *xr = sat_calloc(1, sizeof(*xr));
1263     xr->repo = repo;
1264     xr->id = id;
1265     return xr;
1266   }
1267   Id new_handle() {
1268     return repodata_new_handle($self->repo->repodata + $self->id);
1269   }
1270   void set_id(Id solvid, Id keyname, Id id) {
1271     repodata_set_id($self->repo->repodata + $self->id, solvid, keyname, id);
1272   }
1273   void set_str(Id solvid, Id keyname, const char *str) {
1274     repodata_set_str($self->repo->repodata + $self->id, solvid, keyname, str);
1275   }
1276   void set_poolstr(Id solvid, Id keyname, const char *str) {
1277     repodata_set_poolstr($self->repo->repodata + $self->id, solvid, keyname, str);
1278   }
1279   void add_idarray(Id solvid, Id keyname, Id id) {
1280     repodata_add_idarray($self->repo->repodata + $self->id, solvid, keyname, id);
1281   }
1282   void add_flexarray(Id solvid, Id keyname, Id handle) {
1283     repodata_add_flexarray($self->repo->repodata + $self->id, solvid, keyname, handle);
1284   }
1285   void set_bin_checksum(Id solvid, Id keyname, Id chksumtype, const char *chksum) {
1286     repodata_set_bin_checksum($self->repo->repodata + $self->id, solvid, keyname, chksumtype, (const unsigned char *)chksum);
1287   }
1288   const char *lookup_str(Id solvid, Id keyname) {
1289     return repodata_lookup_str($self->repo->repodata + $self->id, solvid, keyname);
1290   }
1291   SWIGCDATA lookup_bin_checksum(Id solvid, Id keyname, Id *OUTPUT) {
1292     const unsigned char *b;
1293     *OUTPUT = 0;
1294     b = repodata_lookup_bin_checksum($self->repo->repodata + $self->id, solvid, keyname, OUTPUT);
1295     return cdata_void((char *)b, sat_chksum_len(*OUTPUT));
1296   }
1297   void internalize() {
1298     repodata_internalize($self->repo->repodata + $self->id);
1299   }
1300   void create_stubs() {
1301     repodata_create_stubs($self->repo->repodata + $self->id);
1302   }
1303   void write(FILE *fp) {
1304     repodata_write($self->repo->repodata + $self->id, fp, repo_write_stdkeyfilter, 0);
1305   }
1306 }