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