OPTION (ENABLE_PERL "Build the perl bindings?" OFF)
OPTION (ENABLE_PYTHON "Build the python bindings?" OFF)
OPTION (ENABLE_RUBY "Build the ruby bindings?" OFF)
+OPTION (ENABLE_TCL "Build the Tcl bindings?" OFF)
OPTION (USE_VENDORDIRS "Install the bindings in vendor directories?" OFF)
ADD_SUBDIRECTORY (src)
ADD_SUBDIRECTORY (ext)
ADD_SUBDIRECTORY (tools)
-IF (ENABLE_PERL OR ENABLE_PYTHON OR ENABLE_RUBY)
+IF (ENABLE_PERL OR ENABLE_PYTHON OR ENABLE_RUBY OR ENABLE_TCL)
ADD_SUBDIRECTORY (bindings)
-ENDIF (ENABLE_PERL OR ENABLE_PYTHON OR ENABLE_RUBY)
+ENDIF (ENABLE_PERL OR ENABLE_PYTHON OR ENABLE_RUBY OR ENABLE_TCL)
ADD_SUBDIRECTORY (examples)
ADD_SUBDIRECTORY (doc)
CONFIGURE_FILE (${CMAKE_SOURCE_DIR}/package/libsolv.spec.in ${CMAKE_BINARY_DIR}/package/libsolv.spec @ONLY)
ENDMACRO (SPECFILE)
+MACRO (PCFILE)
+ MESSAGE (STATUS "Writing pkg-config file...")
+ CONFIGURE_FILE (${CMAKE_SOURCE_DIR}/libsolv.pc.in ${CMAKE_BINARY_DIR}/libsolv.pc @ONLY)
+ INSTALL( FILES ${CMAKE_BINARY_DIR}/libsolv.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig )
+ENDMACRO (PCFILE)
+
SPECFILE ()
+PCFILE ()
SET (AUTOBUILD_COMMAND
COMMAND ${CMAKE_COMMAND} -E remove ${CMAKE_BINARY_DIR}/package/*.tar.bz2
This file contains the major changes between
libsolv versions:
+Version 0.6.12:
+- new features:
+ * tcl bindings
+- new functions:
+ * solv_chksum_cmp
+
+Version 0.6.11:
+- new functions:
+ * pool_ids2whatprovides
+
+Version 0.6.9:
+- new features:
+ * much improved package choosing code
+ * new testcase dependency format
+ * alternatives introspection
+- new functions:
+ * pool_deb_get_autoinstalled
+ * solver_alternative2str
+ * solver_alternatives_count
+ * solver_get_alternative
+ * solver_rule2pkgrule
+ * testcase_dep2str
+
+Version 0.6.5:
+- new features:
+ * support yum style obsolete handling
+
+Version 0.6.1:
+- API change:
+ repodata_stringify() now returns the string
+- new features:
+ * add BREAK_ORPHANS and KEEP_ORPHANS solver flags
+
Version 0.6.0:
- ABI change: cleaned up and reordered knownid.h
- added support for sha224/sha384/sha512
SET(LIBSOLV_MAJOR "0")
SET(LIBSOLV_MINOR "6")
-SET(LIBSOLV_PATCH "11")
+SET(LIBSOLV_PATCH "12")
IF (ENABLE_RUBY)
ADD_SUBDIRECTORY (ruby)
ENDIF (ENABLE_RUBY)
+IF (ENABLE_TCL)
+ ADD_SUBDIRECTORY (tcl)
+ENDIF (ENABLE_TCL)
#SET (PythonLibs_FIND_VERSION 3)
FIND_PACKAGE (PythonLibs)
-SET (PythonInterp_FIND_VERSION ${PYTHONLIBS_VERSION_STRING})
-FIND_PACKAGE (PythonInterp REQUIRED)
+FIND_PACKAGE (PythonInterp ${PYTHONLIBS_VERSION_STRING} REQUIRED)
EXECUTE_PROCESS(COMMAND ${PYTHON_EXECUTABLE} -c "from sys import stdout; from distutils import sysconfig; stdout.write(sysconfig.get_python_lib(True))" OUTPUT_VARIABLE PYTHON_INSTALL_DIR)
IF (NOT DEFINED PYTHON_VERSION_MAJOR)
%markfunc Pool "mark_Pool";
#endif
-/*
- * binaryblob handling
- */
+/**
+ ** binaryblob handling
+ **/
%{
typedef struct {
%}
%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) {
+#if defined(SWIGTCL)
+ {
+ int bal;
+ unsigned char *ba;
+ res = SWIG_TypeError;
+ ba = Tcl_GetByteArrayFromObj($input, &bal);
+ if (ba) {
+ buf = (char *)ba;
+ size = bal;
+ res = SWIG_OK;
+ alloc = SWIG_OLDOBJ;
+ }
+ }
+#else
res = SWIG_AsCharPtrAndSize($input, &buf, &size, &alloc);
+ if (buf && size)
+ size--;
+#endif
if (!SWIG_IsOK(res)) {
#if defined(SWIGPYTHON)
const void *pybuf = 0;
%typemap(out,noblock=1,fragment="SWIG_FromCharPtrAndSize") BinaryBlob {
#if defined(SWIGPYTHON) && defined(PYTHON3)
$result = $1.data ? Py_BuildValue("y#", $1.data, $1.len) : SWIG_Py_Void();
+#elif defined(SWIGTCL)
+ Tcl_SetObjResult(interp, $1.data ? Tcl_NewByteArrayObj($1.data, $1.len) : NULL);
#else
$result = SWIG_FromCharPtrAndSize($1.data, $1.len);
#if defined(SWIGPERL)
#endif
}
+/**
+ ** Queue handling
+ **/
+
+%typemap(arginit) Queue {
+ queue_init(&$1);
+}
+%typemap(freearg) Queue {
+ queue_free(&$1);
+}
+
#if defined(SWIGPYTHON)
%typemap(in) Queue {
/* Check if is a list */
- queue_init(&$1);
if (PyList_Check($input)) {
int size = PyList_Size($input);
int i = 0;
PyObject *o = PyList_GetItem($input,i);
int v;
int e = SWIG_AsVal_int(o, &v);
- if (!SWIG_IsOK(e)) {
+ if (!SWIG_IsOK(e))
SWIG_exception_fail(SWIG_ArgError(e), "list must contain only integers");
- queue_free(&$1);
- return NULL;
- }
queue_push(&$1, v);
}
} else {
- PyErr_SetString(PyExc_TypeError,"not a list");
- return NULL;
+ SWIG_exception_fail(SWIG_TypeError, "list must contain only integers");
}
}
%enddef
-#endif
+#endif /* SWIGPYTHON */
#if defined(SWIGPERL)
%typemap(in) Queue {
AV *av;
int i, size;
- queue_init(&$1);
if (!SvROK($input) || SvTYPE(SvRV($input)) != SVt_PVAV)
SWIG_croak("Argument $argnum is not an array reference.");
av = (AV*)SvRV($input);
queue_free(&$1);
$result = 0;
}
+
%define Queue2Array(type, step, con) %{
int i;
int cnt = $1.count / step;
%}
%enddef
-#endif
+#endif /* SWIGPERL */
-%typemap(arginit) Queue {
- queue_init(&$1);
-}
-%typemap(freearg) Queue {
- queue_free(&$1);
-}
#if defined(SWIGRUBY)
%typemap(in) Queue {
int size, i;
- VALUE *o;
- queue_init(&$1);
- size = RARRAY_LEN($input);
+ VALUE *o, ary;
+ ary = rb_Array($input);
+ size = RARRAY_LEN(ary);
i = 0;
- o = RARRAY_PTR($input);
+ o = RARRAY_PTR(ary);
for (i = 0; i < size; i++, o++) {
int v;
int e = SWIG_AsVal_int(*o, &v);
if (!SWIG_IsOK(e))
- {
- SWIG_Error(SWIG_RuntimeError, "list must contain only integers");
- SWIG_fail;
- }
+ SWIG_exception_fail(SWIG_TypeError, "list must contain only integers");
queue_push(&$1, v);
}
}
$result = o;
%}
%enddef
-#endif
+#endif /* SWIGRUBY */
+#if defined(SWIGTCL)
+%typemap(in) Queue {
+ /* Check if is a list */
+ int size = 0;
+ int i = 0;
+
+ if (TCL_OK != Tcl_ListObjLength(interp, $input, &size))
+ SWIG_exception_fail(SWIG_TypeError, "argument is not a list");
+ for (i = 0; i < size; i++) {
+ Tcl_Obj *o = NULL;
+ int e, v;
+
+ if (TCL_OK != Tcl_ListObjIndex(interp, $input, i, &o))
+ SWIG_exception_fail(SWIG_IndexError, "failed to retrieve a list member");
+ e = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(o, &v);
+ if (!SWIG_IsOK(e))
+ SWIG_exception_fail(SWIG_ArgError(e), "list must contain only integers");
+ queue_push(&$1, v);
+ }
+}
+
+%typemap(out) Queue {
+ Tcl_Obj *objvx[$1.count];
+ int i;
+
+ for (i = 0; i < $1.count; i++) {
+ objvx[i] = SWIG_From_int($1.elements[i]);
+ }
+ Tcl_SetObjResult(interp, Tcl_NewListObj($1.count, objvx));
+ queue_free(&$1);
+}
+
+%define Queue2Array(type, step, con) %{
+ { /* scope is needed to make the goto of SWIG_exception_fail work */
+ int i;
+ int cnt = $1.count / step;
+ Id *idp = $1.elements;
+ Tcl_Obj *objvx[cnt];
+
+ for (i = 0; i < cnt; i++, idp += step) {
+ Id id = *idp;
+#define result resultx
+#define Tcl_SetObjResult(i, x) resultobj = x
+ type result = con;
+ Tcl_Obj *resultobj;
+ $typemap(out, type)
+ objvx[i] = resultobj;
+#undef Tcl_SetObjResult
+#undef result
+ }
+ queue_free(&$1);
+ Tcl_SetObjResult(interp, Tcl_NewListObj(cnt, objvx));
+ }
+%}
+
+%enddef
+
+%typemap(in) Queue solvejobs {
+ /* Check if is a list */
+ int size = 0;
+ int i = 0;
+
+ if (TCL_OK != Tcl_ListObjLength(interp, $input, &size))
+ SWIG_exception_fail(SWIG_TypeError, "argument is not a list");
+ for (i = 0; i < size; i++) {
+ Tcl_Obj *o = NULL;
+ void *jp;
+ Job *j;
+ int e;
+
+ if (TCL_OK != Tcl_ListObjIndex(interp, $input, i, &o))
+ SWIG_exception_fail(SWIG_IndexError, "failed to retrieve a list member");
+ e = SWIG_ConvertPtr(o, &jp ,SWIGTYPE_p_Job, 0 | 0 );
+ if (!SWIG_IsOK(e))
+ SWIG_exception_fail(SWIG_ArgError(e), "list member is not a Job");
+ j = (Job *)jp;
+ queue_push2(&$1, j->how, j->what);
+ }
+}
+
+#endif /* SWIGTCL */
#if defined(SWIGPERL)
%typemap(out) Repo_solvable_iterator * solvables_iter = Perliterator;
%typemap(out) Dataiterator * = Perliterator;
-#endif
+#endif /* SWIGPERL */
+
+/**
+ ** appdata handling
+ **/
#if defined(SWIGPYTHON)
typedef PyObject *AppObjectPtr;
+%typemap(in) AppObjectPtr {
+ if ($input)
+ Py_INCREF($input);
+ $1 = $input;
+}
%typemap(out) AppObjectPtr {
$result = $1 ? $1 : Py_None;
Py_INCREF($result);
}
-#endif
-#if defined(SWIGPERL)
+#elif defined(SWIGPERL)
typedef SV *AppObjectPtr;
%typemap(in) AppObjectPtr {
- $1 = SvROK($input) ? SvRV($input) : 0;
+ if ($input) {
+ $1 = newSV(0);
+ sv_setsv((SV *)$1, $input);
+ } else
+ $1 = (void *)0;
}
%typemap(out) AppObjectPtr {
- $result = $1 ? newRV_inc($1) : newSV(0);
+ $result = sv_2mortal($1 ? SvREFCNT_inc($1) : newSV(0));
argvi++;
}
-#endif
-#if defined(SWIGRUBY)
+#elif defined(SWIGRUBY)
typedef VALUE AppObjectPtr;
%typemap(in) AppObjectPtr {
$1 = (void *)$input;
%typemap(out) AppObjectPtr {
$result = (VALUE)$1;
}
+#elif defined(SWIGTCL)
+typedef Tcl_Obj *AppObjectPtr;
+%typemap(in) AppObjectPtr {
+ if ($input)
+ Tcl_IncrRefCount($input);
+ $1 = (void *)$input;
+}
+%typemap(out) AppObjectPtr {
+ Tcl_SetObjResult(interp, $1 ? $1 : Tcl_NewObj());
+}
+#else
+#warning AppObjectPtr not defined for this language!
#endif
+/**
+ ** FILE handling
+ **/
#ifdef SWIGPYTHON
%include "file.i"
SWIGINTERN int
#ifdef SWIGRUBY
SWIG_AsValSolvFpPtr(VALUE obj, FILE **val) {
+#elif defined(SWIGTCL)
+SWIG_AsValSolvFpPtr SWIG_TCL_DECL_ARGS_2(void *obj, FILE **val) {
#else
SWIG_AsValSolvFpPtr(void *obj, FILE **val) {
#endif
return SWIG_TypeError;
}
+#if defined(SWIGTCL)
+#define SWIG_AsValSolvFpPtr(x, y) SWIG_AsValSolvFpPtr SWIG_TCL_CALL_ARGS_2(x, y)
+#endif
+
}
+/**
+ ** DepId handling
+ **/
+
%fragment("SWIG_AsValDepId","header") {
SWIGINTERN int
#ifdef SWIGRUBY
SWIG_AsValDepId(VALUE obj, int *val) {
+#elif defined(SWIGTCL)
+SWIG_AsValDepId SWIG_TCL_DECL_ARGS_2(void *obj, int *val) {
#else
SWIG_AsValDepId(void *obj, int *val) {
#endif
void *vptr = 0;
int ecode;
if (!desc) desc = SWIG_TypeQuery("Dep *");
+#ifdef SWIGTCL
+ ecode = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(obj, val);
+#else
ecode = SWIG_AsVal_int(obj, val);
+#endif
if (SWIG_IsOK(ecode))
return ecode;
if ((SWIG_ConvertPtr(obj, &vptr, desc, 0)) == SWIG_OK) {
return SWIG_TypeError;
}
+#ifdef SWIGTCL
+#define SWIG_AsValDepId(x, y) SWIG_AsValDepId SWIG_TCL_CALL_ARGS_2(x, y)
+#endif
}
+/**
+ ** Pool disown helper
+ **/
+
%typemap(out) disown_helper {
-#ifdef SWIGRUBY
+#if defined(SWIGRUBY)
SWIG_ConvertPtr(self, &argp1,SWIGTYPE_p_Pool, SWIG_POINTER_DISOWN | 0 );
-#endif
-#ifdef SWIGPYTHON
+#elif defined(SWIGPYTHON)
SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_Pool, SWIG_POINTER_DISOWN | 0 );
-#endif
-#ifdef SWIGPERL
+#elif defined(SWIGPERL)
SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_Pool, SWIG_POINTER_DISOWN | 0 );
+#elif defined(SWIGTCL)
+ SWIG_ConvertPtr(objv[1], &argp1, SWIGTYPE_p_Pool, SWIG_POINTER_DISOWN | 0);
+#else
+#warning disown_helper not implemented for this language, this is likely going to leak memory
#endif
+
+#ifdef SWIGTCL
+ Tcl_SetObjResult(interp, SWIG_From_int((int)(0)));
+#else
$result = SWIG_From_int((int)(0));
+#endif
}
+
+/**
+ ** misc stuff
+ **/
+
%include "typemaps.i"
%typemap(in,numinputs=0,noblock=1) XRule **OUTPUT ($*1_ltype temp) {
%typemaps_asval(%checkcode(INT32), SWIG_AsValDepId, "SWIG_AsValDepId", DepId);
+/**
+ ** the C declarations
+ **/
+
%{
#include <stdbool.h>
#include <stdio.h>
#include <sys/utsname.h>
#include <sys/types.h>
#include <unistd.h>
+#include <fcntl.h>
/* argh, swig undefs bool for perl */
#ifndef bool
#include "repo_autopattern.h"
#endif
#include "solv_xfopen.h"
+#include "testcase.h"
/* for old ruby versions */
#ifndef RARRAY_PTR
typedef int disown_helper;
+struct myappdata {
+ void *appdata;
+ int disowned;
+};
+
+
%}
+/**
+ ** appdata helpers
+ **/
+
+#ifdef SWIGRUBY
+
+%{
+SWIGINTERN void appdata_disown_helper(void *appdata) {
+}
+SWIGINTERN void appdata_clr_helper(void **appdatap) {
+ *appdatap = 0;
+}
+SWIGINTERN void appdata_set_helper(void **appdatap, void *appdata) {
+ *appdatap = appdata;
+}
+SWIGINTERN void *appdata_get_helper(void *appdata) {
+ return appdata;
+}
+%}
+
+#elif defined(SWIGTCL)
+
+%{
+SWIGINTERN void appdata_disown_helper(void *appdata) {
+}
+SWIGINTERN void appdata_clr_helper(void **appdatap) {
+ if (*appdatap)
+ Tcl_DecrRefCount((Tcl_Obj *)(*appdatap));
+ *appdatap = 0;
+}
+SWIGINTERN void appdata_set_helper(void **appdatap, void *appdata) {
+ appdata_clr_helper(appdatap);
+ *appdatap = appdata;
+}
+SWIGINTERN void *appdata_get_helper(void *appdata) {
+ return appdata;
+}
+%}
+
+#elif defined(SWIGPYTHON)
+
+%{
+SWIGINTERN void appdata_disown_helper(void *appdata) {
+ struct myappdata *myappdata = appdata;
+ if (!myappdata || !myappdata->appdata || myappdata->disowned)
+ return;
+ myappdata->disowned = 1;
+ Py_DECREF((PyObject *)myappdata->appdata);
+}
+SWIGINTERN void appdata_clr_helper(void **appdatap) {
+ struct myappdata *myappdata = *(struct myappdata **)appdatap;
+ if (myappdata && myappdata->appdata && !myappdata->disowned) {
+ Py_DECREF((PyObject *)myappdata->appdata);
+ }
+ *appdatap = solv_free(myappdata);
+}
+SWIGINTERN void appdata_set_helper(void **appdatap, void *appdata) {
+ appdata_clr_helper(appdatap);
+ if (appdata) {
+ struct myappdata *myappdata = *appdatap = solv_calloc(sizeof(struct myappdata), 1);
+ myappdata->appdata = appdata;
+ }
+}
+SWIGINTERN void *appdata_get_helper(void *appdata) {
+ return appdata ? ((struct myappdata *)appdata)->appdata : 0;
+}
+
+%}
+
+#elif defined(SWIGPERL)
+
+%{
+SWIGINTERN void appdata_disown_helper(void *appdata) {
+ struct myappdata *myappdata = appdata;
+ SV *rsv;
+ if (!myappdata || !myappdata->appdata || myappdata->disowned)
+ return;
+ rsv = myappdata->appdata;
+ if (!SvROK(rsv))
+ return;
+ myappdata->appdata = SvRV(rsv);
+ myappdata->disowned = 1;
+ SvREFCNT_dec(rsv);
+}
+SWIGINTERN void appdata_clr_helper(void **appdatap) {
+ struct myappdata *myappdata = *(struct myappdata **)appdatap;
+ if (myappdata && myappdata->appdata && !myappdata->disowned) {
+ SvREFCNT_dec((SV *)myappdata->appdata);
+ }
+ *appdatap = solv_free(myappdata);
+}
+SWIGINTERN void appdata_set_helper(void **appdatap, void *appdata) {
+ appdata_clr_helper(appdatap);
+ if (appdata) {
+ struct myappdata *myappdata = *appdatap = solv_calloc(sizeof(struct myappdata), 1);
+ myappdata->appdata = appdata;
+ }
+}
+SWIGINTERN void *appdata_get_helper(void *appdata) {
+ struct myappdata *myappdata = appdata;
+ if (!myappdata || !myappdata->appdata)
+ return 0;
+ return myappdata->disowned ? newRV_noinc((SV *)myappdata->appdata) : myappdata->appdata;
+}
+
+%}
+
+#else
+#warning appdata helpers not implemented for this language
+#endif
+
+
+/**
+ ** the SWIG declarations defining the API
+ **/
+
#ifdef SWIGRUBY
%mixin Dataiterator "Enumerable";
%mixin Pool_solvable_iterator "Enumerable";
%constant int REL_GT;
%constant int REL_LT;
%constant int REL_ARCH;
+%constant int REL_AND;
+%constant int REL_OR;
+%constant int REL_WITH;
+%constant int REL_COND;
+%constant int REL_ELSE;
typedef struct {
Pool* const pool;
%nodefaultctor Pool;
%nodefaultdtor Pool;
typedef struct {
- AppObjectPtr appdata;
} Pool;
%nodefaultctor Repo;
int priority;
int subpriority;
int const nsolvables;
- AppObjectPtr appdata;
} Repo;
%nodefaultctor Solver;
SolvFp *sfp;
FILE *fp;
fd = dup(fd);
- fp = fd == -1 ? 0 : solv_xfopen_fd(fn, fd, mode);
- if (!fp)
+ if (fd == -1)
return 0;
+ fcntl(fd, F_SETFD, FD_CLOEXEC);
+ fp = solv_xfopen_fd(fn, fd, mode);
+ if (!fp) {
+ close(fd);
+ return 0;
+ }
sfp = solv_calloc(1, sizeof(SolvFp));
sfp->fp = fp;
return sfp;
fp = solv_xfopen(fn, mode);
if (!fp)
return 0;
+ if (fileno(fp) != -1)
+ fcntl(fileno(fp), F_SETFD, FD_CLOEXEC);
sfp = solv_calloc(1, sizeof(SolvFp));
sfp->fp = fp;
return sfp;
int dup() {
return $self->fp ? dup(fileno($self->fp)) : -1;
}
+ bool write(const unsigned char *str, size_t len) {
+ return fwrite(str, len, 1, $self->fp) == 1;
+ }
bool flush() {
if (!$self->fp)
return 1;
$self->fp = 0;
return ret;
}
+ void cloexec(bool state) {
+ if (!$self->fp || fileno($self->fp) == -1)
+ return;
+ fcntl(fileno($self->fp), F_SETFD, state ? FD_CLOEXEC : 0);
+ }
}
%extend Job {
return pool_isemptyupdatejob($self->pool, $self->how, $self->what);
}
+#if defined(SWIGTCL)
+ %rename("==") __eq__;
+#endif
bool __eq__(Job *j) {
return $self->pool == j->pool && $self->how == j->how && $self->what == j->what;
}
+#if defined(SWIGTCL)
+ %rename("!=") __ne__;
+#endif
bool __ne__(Job *j) {
return !Job___eq__($self, j);
}
-#if defined(SWIGPERL)
+#if defined(SWIGPERL) || defined(SWIGTCL)
%rename("str") __str__;
#endif
const char *__str__() {
return pool_job2str($self->pool, $self->how, $self->what, 0);
}
+#if defined(SWIGPERL) || defined(SWIGTCL)
+ %rename("repr") __repr__;
+#endif
const char *__repr__() {
const char *str = pool_job2str($self->pool, $self->how, $self->what, ~0);
return pool_tmpjoin($self->pool, "<Job ", str, ">");
return q;
}
-#if defined(SWIGPERL)
+#if defined(SWIGPERL) || defined(SWIGTCL)
%rename("str") __str__;
#endif
const char *__str__() {
return pool_selection2str($self->pool, &$self->q, 0);
}
+#if defined(SWIGPERL) || defined(SWIGTCL)
+ %rename("repr") __repr__;
+#endif
const char *__repr__() {
const char *str = pool_selection2str($self->pool, &$self->q, ~0);
return pool_tmpjoin($self->pool, "<Selection ", str, ">");
return 0;
return solv_chksum_create_from_bin(type, buf);
}
+ %newobject from_bin;
+ static Chksum *from_bin(Id type, const unsigned char *str, size_t len) {
+ return len == solv_chksum_len(type) ? solv_chksum_create_from_bin(type, str) : 0;
+ }
+#if defined(SWIGPERL)
+ %perlcode {
+ undef *solv::Chksum::from_bin;
+ *solv::Chksum::from_bin = sub {
+ my $pkg = shift;
+ my $self = solvc::Chksum_from_bin(@_);
+ bless $self, $pkg if defined $self;
+ };
+ }
+#endif
~Chksum() {
solv_chksum_free($self, 0);
}
return solv_chksum_type2str(solv_chksum_get_type($self));
}
+#if defined(SWIGTCL)
+ %rename("==") __eq__;
+#endif
bool __eq__(Chksum *chk) {
- int l;
- const unsigned char *b, *bo;
- if (!chk)
- return 0;
- if (solv_chksum_get_type($self) != solv_chksum_get_type(chk))
- return 0;
- b = solv_chksum_get($self, &l);
- bo = solv_chksum_get(chk, 0);
- return memcmp(b, bo, l) == 0;
+ return solv_chksum_cmp($self, chk);
}
+#if defined(SWIGTCL)
+ %rename("!=") __ne__;
+#endif
bool __ne__(Chksum *chk) {
- return !Chksum___eq__($self, chk);
+ return !solv_chksum_cmp($self, chk);
}
#if defined(SWIGRUBY)
%rename("to_s") __str__;
#endif
-#if defined(SWIGPERL)
+#if defined(SWIGPERL) || defined(SWIGTCL)
%rename("str") __str__;
#endif
%newobject __str__;
solv_free((void *)h);
return str;
}
+#if defined(SWIGPERL) || defined(SWIGTCL)
+ %rename("repr") __repr__;
+#endif
%newobject __repr__;
const char *__repr__() {
const char *h = Chksum___str__($self);
return SWIG_IsOK(ecode) ? vresult : 0;
}
%}
- void set_loadcallback(PyObject *callable) {
+ void clr_loadcallback() {
if ($self->loadcallback == loadcallback) {
PyObject *obj = $self->loadcallbackdata;
Py_DECREF(obj);
+ pool_setloadcallback($self, 0, 0);
}
+ }
+ void set_loadcallback(PyObject *callable) {
+ Pool_clr_loadcallback($self);
if (callable) {
Py_INCREF(callable);
+ pool_setloadcallback($self, loadcallback, callable);
}
- pool_setloadcallback($self, callable ? loadcallback : 0, callable);
}
-#endif
-#if defined(SWIGPERL)
+#elif defined(SWIGPERL)
%{
SWIGINTERN int loadcallback(Pool *pool, Repodata *data, void *d) {
int count;
return ret;
}
%}
- void set_loadcallback(SV *callable) {
- if ($self->loadcallback == loadcallback)
+ void clr_loadcallback() {
+ if ($self->loadcallback == loadcallback) {
SvREFCNT_dec($self->loadcallbackdata);
- if (callable)
+ pool_setloadcallback($self, 0, 0);
+ }
+ }
+ void set_loadcallback(SV *callable) {
+ Pool_clr_loadcallback($self);
+ if (callable) {
SvREFCNT_inc(callable);
- pool_setloadcallback($self, callable ? loadcallback : 0, callable);
+ pool_setloadcallback($self, loadcallback, callable);
+ }
}
-#endif
-
-#if defined(SWIGRUBY)
+#elif defined(SWIGRUBY)
%{
SWIGINTERN int loadcallback(Pool *pool, Repodata *data, void *d) {
XRepodata *xd = new_XRepodata(data->repo, data->repodataid);
}
}
%}
+ void clr_loadcallback() {
+ pool_setloadcallback($self, 0, 0);
+ }
%typemap(in, numinputs=0) VALUE callable {
$1 = rb_block_given_p() ? rb_block_proc() : 0;
}
void set_loadcallback(VALUE callable) {
pool_setloadcallback($self, callable ? loadcallback : 0, (void *)callable);
}
+#elif defined(SWIGTCL)
+ %{
+ typedef struct {
+ Tcl_Interp *interp;
+ Tcl_Obj *obj;
+ } tcl_callback_t;
+ SWIGINTERN int loadcallback(Pool *pool, Repodata *data, void *d) {
+ tcl_callback_t *callback_var = (tcl_callback_t *)d;
+ Tcl_Interp *interp = callback_var->interp;
+ XRepodata *xd = new_XRepodata(data->repo, data->repodataid);
+ int result, ecode = 0, vresult = 0;
+ Tcl_Obj *objvx[2];
+ objvx[0] = callback_var->obj;
+ objvx[1] = SWIG_NewInstanceObj(SWIG_as_voidptr(xd), SWIGTYPE_p_XRepodata, 0);
+ Tcl_IncrRefCount(objvx[1]);
+ result = Tcl_EvalObjv(interp, sizeof(objvx)/sizeof(*objvx), objvx, TCL_EVAL_GLOBAL);
+ Tcl_DecrRefCount(objvx[1]);
+ if (result != TCL_OK)
+ return 0; /* exception */
+ ecode = SWIG_AsVal_int(interp, Tcl_GetObjResult(interp), &vresult);
+ return SWIG_IsOK(ecode) ? vresult : 0;
+ }
+ %}
+ void clr_loadcallback() {
+ if ($self->loadcallback == loadcallback) {
+ tcl_callback_t *callback_var = $self->loadcallbackdata;
+ Tcl_DecrRefCount(callback_var->obj);
+ solv_free(callback_var);
+ pool_setloadcallback($self, 0, 0);
+ }
+ }
+ void set_loadcallback(Tcl_Obj *callable, Tcl_Interp *interp) {
+ Pool_clr_loadcallback($self);
+ if (callable) {
+ tcl_callback_t *callback_var = solv_malloc(sizeof(tcl_callback_t));
+ Tcl_IncrRefCount(callable);
+ callback_var->interp = interp;
+ callback_var->obj = callable;
+ pool_setloadcallback($self, loadcallback, callback_var);
+ }
+ }
+#else
+#warning loadcallback not implemented for this language
#endif
~Pool() {
- Pool_set_loadcallback($self, 0);
- pool_free($self);
+ Pool *pool = $self;
+ Id repoid;
+ Repo *repo;
+ FOR_REPOS(repoid, repo)
+ appdata_clr_helper(&repo->appdata);
+ Pool_clr_loadcallback(pool);
+ appdata_clr_helper(&pool->appdata);
+ pool_free(pool);
}
disown_helper free() {
- Pool_set_loadcallback($self, 0);
- pool_free($self);
+ Pool *pool = $self;
+ Id repoid;
+ Repo *repo;
+ FOR_REPOS(repoid, repo)
+ appdata_clr_helper(&repo->appdata);
+ Pool_clr_loadcallback(pool);
+ appdata_clr_helper(&pool->appdata);
+ pool_free(pool);
return 0;
}
disown_helper disown() {
return 0;
}
+ AppObjectPtr appdata;
+ %{
+ SWIGINTERN void Pool_appdata_set(Pool *pool, AppObjectPtr appdata) {
+ appdata_set_helper(&pool->appdata, appdata);
+ }
+ SWIGINTERN AppObjectPtr Pool_appdata_get(Pool *pool) {
+ return appdata_get_helper(pool->appdata);
+ }
+ %}
+ void appdata_disown() {
+ appdata_disown_helper($self->appdata);
+ }
+
Id str2id(const char *str, bool create=1) {
return pool_str2id($self, str, create);
}
SWIGINTERN void Pool_installed_set(Pool *pool, Repo *installed) {
pool_set_installed(pool, installed);
}
- Repo *Pool_installed_get(Pool *pool) {
+ SWIGINTERN Repo *Pool_installed_get(Pool *pool) {
return pool->installed;
}
- const char *Pool_errstr_get(Pool *pool) {
+ SWIGINTERN const char *Pool_errstr_get(Pool *pool) {
return pool_errstr(pool);
}
%}
#endif
void free(bool reuseids = 0) {
+ appdata_clr_helper(&$self->appdata);
repo_free($self, reuseids);
}
void empty(bool reuseids = 0) {
bool isempty() {
return !$self->nsolvables;
}
+
+ AppObjectPtr appdata;
+ %{
+ SWIGINTERN void Repo_appdata_set(Repo *repo, AppObjectPtr appdata) {
+ appdata_set_helper(&repo->appdata, appdata);
+ }
+ SWIGINTERN AppObjectPtr Repo_appdata_get(Repo *repo) {
+ return appdata_get_helper(repo->appdata);
+ }
+ %}
+
bool add_solv(const char *name, int flags = 0) {
FILE *fp = fopen(name, "r");
int r;
}
#endif
+#if defined(SWIGTCL)
+ %rename("==") __eq__;
+#endif
bool __eq__(Repo *repo) {
return $self == repo;
}
+#if defined(SWIGTCL)
+ %rename("!=") __ne__;
+#endif
bool __ne__(Repo *repo) {
return $self != repo;
}
-#if defined(SWIGPERL)
+#if defined(SWIGPERL) || defined(SWIGTCL)
%rename("str") __str__;
#endif
%newobject __str__;
sprintf(buf, "Repo#%d", $self->repoid);
return solv_strdup(buf);
}
+#if defined(SWIGPERL) || defined(SWIGTCL)
+ %rename("repr") __repr__;
+#endif
%newobject __repr__;
const char *__repr__() {
char buf[20];
*solv::Datamatch::str = *solvc::Datamatch_stringify;
}
#endif
+#if defined(SWIGTCL)
+ %rename("stringify") __str__;
+#endif
const char *__str__() {
KeyValue kv = $self->kv;
const char *str = repodata_stringify($self->pool, $self->data, $self->key, &kv, SEARCH_FILES | SEARCH_CHECKSUMS);
const char *str() {
return pool_dep2str($self->pool, $self->id);
}
+#if defined(SWIGTCL)
+ %rename("==") __eq__;
+#endif
bool __eq__(Dep *s) {
return $self->pool == s->pool && $self->id == s->id;
}
+#if defined(SWIGTCL)
+ %rename("!=") __ne__;
+#endif
bool __ne__(Dep *s) {
return !Dep___eq__($self, s);
}
-#if defined(SWIGPERL)
+#if defined(SWIGPERL) || defined(SWIGTCL)
%rename("str") __str__;
#endif
const char *__str__() {
return pool_dep2str($self->pool, $self->id);
}
+#if defined(SWIGPERL) || defined(SWIGTCL)
+ %rename("repr") __repr__;
+#endif
%newobject __repr__;
const char *__repr__() {
char buf[20];
return pool_evrcmp($self->pool, $self->pool->solvables[$self->id].evr, s2->pool->solvables[s2->id].evr, EVRCMP_COMPARE);
}
+#if defined(SWIGTCL)
+ %rename("==") __eq__;
+#endif
bool __eq__(XSolvable *s) {
return $self->pool == s->pool && $self->id == s->id;
}
+#if defined(SWIGTCL)
+ %rename("!=") __ne__;
+#endif
bool __ne__(XSolvable *s) {
return !XSolvable___eq__($self, s);
}
-#if defined(SWIGPERL)
+#if defined(SWIGPERL) || defined(SWIGTCL)
%rename("str") __str__;
#endif
const char *__str__() {
return pool_solvid2str($self->pool, $self->id);
}
+#if defined(SWIGPERL) || defined(SWIGTCL)
+ %rename("repr") __repr__;
+#endif
%newobject __repr__;
const char *__repr__() {
char buf[20];
queue_push(&q, i);
return q;
}
-#if defined(SWIGPERL)
+#if defined(SWIGPERL) || defined(SWIGTCL)
%rename("str") __str__;
#endif
const char *__str__() {
%newobject Job;
Job *Job() {
Id extraflags = solver_solutionelement_extrajobflags($self->solv, $self->problemid, $self->solutionid);
- if ($self->type == SOLVER_SOLUTION_JOB || SOLVER_SOLUTION_POOLJOB)
+ if ($self->type == SOLVER_SOLUTION_JOB || $self->type == SOLVER_SOLUTION_POOLJOB)
return new_Job($self->solv->pool, SOLVER_NOOP, 0);
if ($self->type == SOLVER_SOLUTION_INFARCH || $self->type == SOLVER_SOLUTION_DISTUPGRADE || $self->type == SOLVER_SOLUTION_BEST)
return new_Job($self->solv->pool, SOLVER_INSTALL|SOLVER_SOLVABLE|SOLVER_NOTBYUSER|extraflags, $self->p);
queue_push(&q, i);
return q;
}
+#if defined(SWIGTCL)
+ %typemap(out) Queue solve Queue2Array(Problem *, 1, new_Problem(arg1, id));
+ %newobject solve;
+ Queue solve(Queue solvejobs) {
+ Queue q;
+ int i, cnt;
+ queue_init(&q);
+ solver_solve($self, &solvejobs);
+ cnt = solver_problem_count($self);
+ for (i = 1; i <= cnt; i++)
+ queue_push(&q, i);
+ return q;
+ }
+#endif
+
%newobject transaction;
Transaction *transaction() {
return solver_create_transaction($self);
return reason;
}
+ %newobject describe_weakdep_decision_raw;
+ Queue describe_weakdep_decision_raw(XSolvable *s) {
+ Queue q;
+ queue_init(&q);
+ solver_describe_weakdep_decision($self, s->id, &q);
+ return q;
+ }
+#if defined(SWIGPYTHON)
+ %pythoncode {
+ def describe_weakdep_decision(self, s):
+ d = iter(self.describe_weakdep_decision_raw(s))
+ return [ (t, XSolvable(self.pool, sid), Dep(self.pool, id)) for t, sid, id in zip(d, d, d) ]
+ }
+#endif
+#if defined(SWIGPERL)
+ %perlcode {
+ sub solv::Solver::describe_weakdep_decision {
+ my ($self, $s) = @_;
+ my $pool = $self->{'pool'};
+ my @res;
+ my @d = $self->describe_weakdep_decision_raw($s);
+ push @res, [ splice(@d, 0, 3) ] while @d;
+ return map { [ $_->[0], solv::XSolvable->new($pool, $_->[1]), solv::Dep->new($pool, $_->[2]) ] } @res;
+ }
+ }
+#endif
+#if defined(SWIGRUBY)
+%init %{
+rb_eval_string(
+ "class Solv::Solver\n"
+ " def describe_weakdep_decision(s)\n"
+ " 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"
+ " end\n"
+ "end\n"
+ );
+%}
+#endif
+
int alternatives_count() {
return solver_alternatives_count($self);
}
queue_push(&q, i);
return q;
}
+
+ bool write_testcase(const char *dir) {
+ return testcase_write($self, dir, TESTCASE_RESULT_TRANSACTION | TESTCASE_RESULT_PROBLEMS, 0, 0);
+ }
}
%extend Transaction {
return q;
}
+#if defined(SWIGTCL)
+ %rename("==") __eq__;
+#endif
bool __eq__(XRule *xr) {
return $self->solv == xr->solv && $self->id == xr->id;
}
+#if defined(SWIGTCL)
+ %rename("!=") __ne__;
+#endif
bool __ne__(XRule *xr) {
return !XRule___eq__($self, xr);
}
+#if defined(SWIGPERL) || defined(SWIGTCL)
+ %rename("repr") __repr__;
+#endif
%newobject __repr__;
const char *__repr__() {
char buf[20];
Repodata *data = repo_id2repodata($self->repo, $self->id);
repodata_extend_block(data, data->repo->start, data->repo->end - data->repo->start);
}
+#if defined(SWIGTCL)
+ %rename("==") __eq__;
+#endif
bool __eq__(XRepodata *xr) {
return $self->repo == xr->repo && $self->id == xr->id;
}
+#if defined(SWIGTCL)
+ %rename("!=") __ne__;
+#endif
bool __ne__(XRepodata *xr) {
return !XRepodata___eq__($self, xr);
}
+#if defined(SWIGPERL) || defined(SWIGTCL)
+ %rename("repr") __repr__;
+#endif
%newobject __repr__;
const char *__repr__() {
char buf[20];
return r;
}
-#if defined(SWIGPERL)
+#if defined(SWIGPERL) || defined(SWIGTCL)
%rename("str") __str__;
#endif
const char *__str__() {
return solver_alternative2str($self->solv, $self->type, $self->type == SOLVER_ALTERNATIVE_TYPE_RULE ? $self->rid : $self->dep_id, $self->from_id);
}
}
+
+#if defined(SWIGTCL)
+%init %{
+ Tcl_Eval(interp,
+"proc solv::iter {varname iter body} {\n"\
+" while 1 {\n"\
+" set value [$iter __next__]\n"\
+" if {$value eq \"NULL\"} { break }\n"\
+" uplevel [list set $varname $value]\n"\
+" set code [catch {uplevel $body} result]\n"\
+" switch -exact -- $code {\n"\
+" 0 {}\n"\
+" 3 { return }\n"\
+" 4 {}\n"\
+" default { return -code $code $result }\n"\
+" }\n"\
+" }\n"\
+"}\n"
+ );
+%}
+#endif
+
--- /dev/null
+FIND_PACKAGE (TCL)
+
+SET (SWIG_TCL_FLAGS -namespace -pkgversion ${VERSION})
+
+EXECUTE_PROCESS (
+ COMMAND echo "puts -nonewline [lindex [::tcl::tm::list] end]"
+ COMMAND ${TCL_TCLSH}
+ OUTPUT_VARIABLE TCL_INSTALL_DIR
+)
+
+MESSAGE (STATUS "Tclsh executable: ${TCL_TCLSH}")
+MESSAGE (STATUS "Tcl installation dir: ${TCL_INSTALL_DIR}")
+
+ADD_CUSTOM_COMMAND (
+ OUTPUT solv_tcl.c
+ COMMAND ${SWIG_EXECUTABLE} ${SWIG_FLAGS} -tcl ${SWIG_TCL_FLAGS} -I${CMAKE_SOURCE_DIR}/src -o solv_tcl.c ${CMAKE_SOURCE_DIR}/bindings/solv.i
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+ DEPENDS ${CMAKE_SOURCE_DIR}/bindings/solv.i
+)
+
+ADD_DEFINITIONS(-Wno-unused)
+INCLUDE_DIRECTORIES (${TCL_INCLUDE_PATH})
+
+ADD_LIBRARY (bindings_tcl SHARED solv_tcl.c)
+SET_TARGET_PROPERTIES (bindings_tcl PROPERTIES PREFIX "" OUTPUT_NAME "solv-${VERSION}" INSTALL_NAME_DIR "${TCL_INSTALL_DIR}")
+TARGET_LINK_LIBRARIES (bindings_tcl libsolvext libsolv ${TCL_LIBRARY} ${SYSTEM_LIBRARIES})
+INSTALL (TARGETS bindings_tcl LIBRARY DESTINATION ${TCL_INSTALL_DIR})
+
+ADD_CUSTOM_COMMAND (
+ OUTPUT solv.tm
+ COMMAND sed -e "s/__VERSION__/${VERSION}/" ${CMAKE_SOURCE_DIR}/bindings/tcl/solv.tm.in >${CMAKE_CURRENT_BINARY_DIR}/solv.tm
+ DEPENDS ${CMAKE_SOURCE_DIR}/bindings/tcl/solv.tm.in
+ COMMENT "Creating Tcl module to load libsolv"
+)
+ADD_CUSTOM_TARGET (solv_tm ALL DEPENDS solv.tm)
+SET_SOURCE_FILES_PROPERTIES (solv.tm PROPERTIES GENERATED TRUE)
+
+INSTALL (FILES ${CMAKE_CURRENT_BINARY_DIR}/solv.tm DESTINATION ${TCL_INSTALL_DIR} RENAME solv-${VERSION}.tm)
--- /dev/null
+package require Tcl
+
+#package provide solv __VERSION__
+load [::file join [::file dirname [::info script]] "solv-__VERSION__[::info sharedlibextension]"]
.\" Title: appdata2solv
.\" Author: [see the "Author" section]
.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
-.\" Date: 09/25/2014
+.\" Date: 08/26/2015
.\" Manual: LIBSOLV
.\" Source: libsolv
.\" Language: English
.\"
-.TH "APPDATA2SOLV" "1" "09/25/2014" "libsolv" "LIBSOLV"
+.TH "APPDATA2SOLV" "1" "08/26/2015" "libsolv" "LIBSOLV"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
.\" Title: archpkgs2solv
.\" Author: [see the "Author" section]
.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
-.\" Date: 09/25/2014
+.\" Date: 08/26/2015
.\" Manual: LIBSOLV
.\" Source: libsolv
.\" Language: English
.\"
-.TH "ARCHPKGS2SOLV" "1" "09/25/2014" "libsolv" "LIBSOLV"
+.TH "ARCHPKGS2SOLV" "1" "08/26/2015" "libsolv" "LIBSOLV"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
.\" Title: archrepo2solv
.\" Author: [see the "Author" section]
.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
-.\" Date: 09/25/2014
+.\" Date: 08/26/2015
.\" Manual: LIBSOLV
.\" Source: libsolv
.\" Language: English
.\"
-.TH "ARCHREPO2SOLV" "1" "09/25/2014" "libsolv" "LIBSOLV"
+.TH "ARCHREPO2SOLV" "1" "08/26/2015" "libsolv" "LIBSOLV"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
.\" Title: comps2solv
.\" Author: [see the "Author" section]
.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
-.\" Date: 09/25/2014
+.\" Date: 08/26/2015
.\" Manual: LIBSOLV
.\" Source: libsolv
.\" Language: English
.\"
-.TH "COMPS2SOLV" "1" "09/25/2014" "libsolv" "LIBSOLV"
+.TH "COMPS2SOLV" "1" "08/26/2015" "libsolv" "LIBSOLV"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
.\" Title: deb2solv
.\" Author: [see the "Author" section]
.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
-.\" Date: 09/25/2014
+.\" Date: 08/26/2015
.\" Manual: LIBSOLV
.\" Source: libsolv
.\" Language: English
.\"
-.TH "DEB2SOLV" "1" "09/25/2014" "libsolv" "LIBSOLV"
+.TH "DEB2SOLV" "1" "08/26/2015" "libsolv" "LIBSOLV"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
.\" Title: deltainfoxml2solv
.\" Author: [see the "Author" section]
.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
-.\" Date: 09/24/2014
+.\" Date: 08/26/2015
.\" Manual: LIBSOLV
.\" Source: libsolv
.\" Language: English
.\"
-.TH "DELTAINFOXML2SOLV" "1" "09/24/2014" "libsolv" "LIBSOLV"
+.TH "DELTAINFOXML2SOLV" "1" "08/26/2015" "libsolv" "LIBSOLV"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
.\" Title: dumpsolv
.\" Author: [see the "Author" section]
.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
-.\" Date: 09/22/2014
+.\" Date: 08/26/2015
.\" Manual: LIBSOLV
.\" Source: libsolv
.\" Language: English
.\"
-.TH "DUMPSOLV" "1" "09/22/2014" "libsolv" "LIBSOLV"
+.TH "DUMPSOLV" "1" "08/26/2015" "libsolv" "LIBSOLV"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
if (!/^[a-zA-Z0-9_]+$/) {
$_ = " $_";
$_ = "$_ ";
- s/(?<=[^a-zA-Z_\&:\.\'\";])(?!solv\W|Solv\W|Pool\W)([\$\@a-zA-Z_][a-zA-Z0-9_]*)(?=[^a-zA-Z0-9_\(;\[])(?!::)(?! [^=])/<-S><I>$1<-I><S>/g;
+ if (s/^ TCL +/ /) {
+ s/(\$[a-zA-Z_][a-zA-Z0-9_]*)/<-S><I>$1<-I><S>/g;
+ } else {
+ s/(?<=[^a-zA-Z_\&:\.\'\";])(?!solv\W|Solv\W|Pool\W)([\$\@a-zA-Z_][a-zA-Z0-9_]*)(?=[^a-zA-Z0-9_\(;\[])(?!::)(?! [^=])/<-S><I>$1<-I><S>/g;
+ }
# fixup for perl bare words
s/{<-S><I>([a-zA-Z_][a-zA-Z0-9]*)<-I><S>}/{$1}/g;
# fixup for callbackfunctions
.\" Title: helix2solv
.\" Author: [see the "Author" section]
.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
-.\" Date: 09/24/2014
+.\" Date: 08/26/2015
.\" Manual: LIBSOLV
.\" Source: libsolv
.\" Language: English
.\"
-.TH "HELIX2SOLV" "1" "09/24/2014" "libsolv" "LIBSOLV"
+.TH "HELIX2SOLV" "1" "08/26/2015" "libsolv" "LIBSOLV"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
.\" Title: installcheck
.\" Author: [see the "Author" section]
.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
-.\" Date: 09/22/2014
+.\" Date: 08/26/2015
.\" Manual: LIBSOLV
.\" Source: libsolv
.\" Language: English
.\"
-.TH "INSTALLCHECK" "1" "09/22/2014" "libsolv" "LIBSOLV"
+.TH "INSTALLCHECK" "1" "08/26/2015" "libsolv" "LIBSOLV"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
.\" Title: Libsolv-Bindings
.\" Author: [see the "Author" section]
.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
-.\" Date: 09/29/2014
+.\" Date: 08/28/2015
.\" Manual: LIBSOLV
.\" Source: libsolv
.\" Language: English
.\"
-.TH "LIBSOLV\-BINDINGS" "3" "09/29/2014" "libsolv" "LIBSOLV"
+.TH "LIBSOLV\-BINDINGS" "3" "08/28/2015" "libsolv" "LIBSOLV"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
.if n \{\
.RE
.\}
+.SH "TCL SPECIFICS"
+.sp
+Libsolv\(cqs tcl bindings can be loaded with the following statement:
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+\fBpackage require solv\fR
+.fi
+.if n \{\
+.RE
+.\}
+.sp
+Objects are either created by calling class name prefixed with \(lqnew_\(rq, or they are returned by calling methods on other objects\&.
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+\fBset pool [solv::new_Pool]\fR
+\fBset repo [\fR\fI$pool\fR \fBadd_repo "my_first_repo"]\fR
+.fi
+.if n \{\
+.RE
+.\}
+.sp
+Swig provides a \(lqcget\(rq method to read object attributes, and a \(lqconfigure\(rq method to write them:
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+\fI$pool\fR \fBconfigure \-appdata 42\fR
+\fBputs "appdata is [\fR\fI$pool\fR \fBcget \-appdata]"\fR
+.fi
+.if n \{\
+.RE
+.\}
+.sp
+The tcl bindings provide a little helper to work with iterators in a foreach style:
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+\fBset iter [\fR\fI$pool\fR \fBsolvables_iter]\fR
+\fBsolv::iter s\fR \fI$iter\fR \fB{ \&.\&.\&. }\fR
+.fi
+.if n \{\
+.RE
+.\}
+.sp
+libsolv\(cqs arrays are mapped to tcl\(cqs lists:
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+\fBset jobs [list\fR \fI$job1 $job2\fR\fB]\fR
+\fBset problems [\fR\fI$solver\fR \fBsolve\fR \fI$jobs\fR\fB]\fR
+\fBputs "We have [llength\fR \fI$problems\fR\fB] problems\&.\&.\&."\fR
+.fi
+.if n \{\
+.RE
+.\}
+.sp
+Stringification is done by calling the object\(cqs \(lqstr\(rq method\&.
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+\fBputs [\fR\fI$dep\fR \fBstr]\fR
+.fi
+.if n \{\
+.RE
+.\}
+.sp
+There is one exception: you have to use \(lqstringify\(rq for Datamatch objects, as swig reports a clash with the \(lqstr\(rq attribute\&. Some objects also support a \(lq==\(rq method for equality tests, and a \(lq!=\(rq method\&.
+.sp
+Swig implements all constants as numeric variables, constants belonging to a libsolv class are prefixed with the class name:
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+\fI$pool\fR \fBset_flag\fR \fI$solv\fR\fB::Pool_POOL_FLAG_OBSOLETEUSESCOLORS 1\fR
+\fBputs [\fR\fI$solvable\fR \fBlookup_str\fR \fI$solv\fR\fB::SOLVABLE_SUMMARY]\fR
+.fi
+.if n \{\
+.RE
+.\}
.SH "THE SOLV CLASS"
.sp
This is the main namespace of the library, you cannot create objects of this type but it contains some useful constants\&.
.\}
.sp
Set the callback function called when repository metadata needs to be loaded on demand\&. To make use of this feature, you need to create repodata stubs that tell the library which data is available but not loaded\&. If later on the data needs to be accessed, the callback function is called with a repodata argument\&. You can then load the data (maybe fetching it first from an remote server)\&. The callback should return true if the data has been made available\&.
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+/* bindings only */
+\fI$pool\fR\fB\->appdata_disown()\fR
+\fIpool\fR\fB\&.appdata_disown()\fR
+\fIpool\fR\fB\&.appdata_disown()\fR
+.fi
+.if n \{\
+.RE
+.\}
+.sp
+Decrement the reference count of the appdata object\&. This can be used to break circular references (e\&.g\&. if the pool\(cqs appdata value points to some meta data structure that contains a pool handle)\&. If used incorrectly, this method can lead to application crashes, so beware\&. (This method is a no\-op for ruby and tcl\&.)
.SS "DATA RETRIEVAL METHODS"
.sp
In the following functions, the \fIkeyname\fR argument describes what to retrieve\&. For the standard cases you can use the available Id constants\&. For example,
.RE
.\}
.sp
-Create an already finalized checksum object\&.
+Create an already finalized checksum object from a hex string\&.
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+\fBChksum Chksum_from_bin(Id\fR \fItype\fR\fB, char *\fR\fIbin\fR\fB)\fR
+my \fI$chksum\fR \fB= solv::Chksum\->from_bin(\fR\fI$type\fR\fB,\fR \fI$bin\fR\fB)\fR;
+\fIchksum\fR \fB= solv\&.Chksum\&.from_bin(\fR\fItype\fR\fB,\fR \fIbin\fR\fB)\fR
+\fIchksum\fR \fB= Solv::Chksum\&.from_bin(\fR\fItype\fR\fB,\fR \fIbin\fR\fB)\fR
+.fi
+.if n \{\
+.RE
+.\}
+.sp
+Create an already finalized checksum object from a binary checksum\&.
.SS "ATTRIBUTES"
.sp
.if n \{\
.RE
.\}
.sp
-Add a string to the checksum\&.
+Add a (binary) string to the checksum\&.
.sp
.if n \{\
.RS 4
.RE
.\}
.sp
-Create a file handle from the specified file descriptor\&. The path argument is only used to select the correct (de\-)compression algorithm, use an empty path if you want to make sure to read/write raw data\&.
+Create a file handle from the specified file descriptor\&. The path argument is only used to select the correct (de\-)compression algorithm, use an empty path if you want to make sure to read/write raw data\&. The file descriptor is dup()ed before the file handle is created\&.
.SS "METHODS"
.sp
.if n \{\
.RS 4
.\}
.nf
+\fBvoid cloexec(bool\fR \fIstate\fR\fB)\fR
+\fI$file\fR\fB\->cloexec(\fR\fI$state\fR\fB)\fR
+\fIfile\fR\fB\&.cloexec(\fR\fIstate\fR\fB)\fR
+\fIfile\fR\fB\&.cloexec(\fR\fIstate\fR\fB)\fR
+.fi
+.if n \{\
+.RE
+.\}
+.sp
+Set the close\-on\-exec flag of the file descriptor\&. The xfopen function returns files with close\-on\-exec turned on, so if you want to pass a file to some other process you need to call cloexec(0) before calling exec\&.
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
\fBint dup()\fR
my \fI$fileno\fR \fB=\fR \fI$file\fR\fB\->dup()\fR;
\fIfileno\fR \fB=\fR \fIfile\fR\fB\&.dup()\fR
.RE
.\}
.sp
-Close the file\&. This is needed for languages like Ruby, that do not destruct objects right after they are no longer referenced\&. In that case, it is good style to close open files so that the file descriptors are freed right away\&. Returns false if there was an error\&.
+Close the file\&. This is needed for languages like Ruby that do not destruct objects right after they are no longer referenced\&. In that case, it is good style to close open files so that the file descriptors are freed right away\&. Returns false if there was an error\&.
.SH "THE REPODATA CLASS"
.sp
The Repodata stores attributes for packages and the repository itself, each repository can have multiple repodata areas\&. You normally only need to directly access them if you implement lazy downloading of repository data\&. Repodata areas are created by calling the repository\(cqs add_repodata() method or by using repo_add methods without the REPO_REUSE_REPODATA or REPO_USE_LOADING flag\&.
puts "empty" if repo.isempty?
+Tcl Specifics
+-------------
+Libsolv's tcl bindings can be loaded with the following statement:
+
+ TCL package require solv
+
+Objects are either created by calling class name prefixed with ``new_'',
+or they are returned by calling methods on other objects.
+
+ TCL set pool [solv::new_Pool]
+ TCL set repo [$pool add_repo "my_first_repo"]
+
+Swig provides a ``cget'' method to read object attributes, and a
+``configure'' method to write them:
+
+ TCL $pool configure -appdata 42
+ TCL puts "appdata is [$pool cget -appdata]"
+
+The tcl bindings provide a little helper to work with iterators in
+a foreach style:
+
+ TCL set iter [$pool solvables_iter]
+ TCL solv::iter s $iter { ... }
+
+libsolv's arrays are mapped to tcl's lists:
+
+ TCL set jobs [list $job1 $job2]
+ TCL set problems [$solver solve $jobs]
+ TCL puts "We have [llength $problems] problems..."
+
+Stringification is done by calling the object's ``str'' method.
+
+ TCL puts [$dep str]
+
+There is one exception: you have to use ``stringify'' for Datamatch
+objects, as swig reports a clash with the ``str'' attribute.
+Some objects also support a ``=='' method for equality tests, and a
+``!='' method.
+
+Swig implements all constants as numeric variables, constants belonging
+to a libsolv class are prefixed with the class name:
+
+ TCL $pool set_flag $solv::Pool_POOL_FLAG_OBSOLETEUSESCOLORS 1
+ TCL puts [$solvable lookup_str $solv::SOLVABLE_SUMMARY]
+
+
The Solv Class
--------------
This is the main namespace of the library, you cannot create objects of this
You can then load the data (maybe fetching it first from an remote server).
The callback should return true if the data has been made available.
+ /* bindings only */
+ $pool->appdata_disown()
+ pool.appdata_disown()
+ pool.appdata_disown()
+
+Decrement the reference count of the appdata object. This can be used to break
+circular references (e.g. if the pool's appdata value points to some meta data
+structure that contains a pool handle). If used incorrectly, this method can
+lead to application crashes, so beware. (This method is a no-op for ruby and tcl.)
+
=== DATA RETRIEVAL METHODS ===
In the following functions, the _keyname_ argument describes what to retrieve.
chksum = solv.Chksum(type, hex)
chksum = Solv::Chksum.new(type, hex)
-Create an already finalized checksum object.
+Create an already finalized checksum object from a hex string.
+
+ Chksum Chksum_from_bin(Id type, char *bin)
+ my $chksum = solv::Chksum->from_bin($type, $bin);
+ chksum = solv.Chksum.from_bin(type, bin)
+ chksum = Solv::Chksum.from_bin(type, bin)
+
+Create an already finalized checksum object from a binary checksum.
=== ATTRIBUTES ===
chksum.add(str)
chksum.add(str)
-Add a string to the checksum.
+Add a (binary) string to the checksum.
void add_fp(FILE *fp)
$chksum->add_fp($file);
Create a file handle from the specified file descriptor. The path argument is
only used to select the correct (de-)compression algorithm, use an empty path
-if you want to make sure to read/write raw data.
+if you want to make sure to read/write raw data. The file descriptor is dup()ed
+before the file handle is created.
=== METHODS ===
Return file file descriptor of the file. If the file is not open, `-1` is
returned.
+ void cloexec(bool state)
+ $file->cloexec($state)
+ file.cloexec(state)
+ file.cloexec(state)
+
+Set the close-on-exec flag of the file descriptor. The xfopen function
+returns files with close-on-exec turned on, so if you want to pass
+a file to some other process you need to call cloexec(0) before calling
+exec.
+
int dup()
my $fileno = $file->dup();
fileno = file.dup()
file.close()
file.close()
-Close the file. This is needed for languages like Ruby, that do not destruct
+Close the file. This is needed for languages like Ruby that do not destruct
objects right after they are no longer referenced. In that case, it is good
style to close open files so that the file descriptors are freed right away.
Returns false if there was an error.
.\" Title: Libsolv-Constantids
.\" Author: [see the "Author" section]
.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
-.\" Date: 03/19/2015
+.\" Date: 08/26/2015
.\" Manual: LIBSOLV
.\" Source: libsolv
.\" Language: English
.\"
-.TH "LIBSOLV\-CONSTANTIDS" "3" "03/19/2015" "libsolv" "LIBSOLV"
+.TH "LIBSOLV\-CONSTANTIDS" "3" "08/26/2015" "libsolv" "LIBSOLV"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
.\" Title: Libsolv-History
.\" Author: [see the "Author" section]
.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
-.\" Date: 09/20/2013
+.\" Date: 08/26/2015
.\" Manual: LIBSOLV
.\" Source: libsolv
.\" Language: English
.\"
-.TH "LIBSOLV\-HISTORY" "3" "09/20/2013" "libsolv" "LIBSOLV"
+.TH "LIBSOLV\-HISTORY" "3" "08/26/2015" "libsolv" "LIBSOLV"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
.\" Title: Libsolv-Pool
.\" Author: [see the "Author" section]
.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
-.\" Date: 10/09/2014
+.\" Date: 08/26/2015
.\" Manual: LIBSOLV
.\" Source: libsolv
.\" Language: English
.\"
-.TH "LIBSOLV\-POOL" "3" "10/09/2014" "libsolv" "LIBSOLV"
+.TH "LIBSOLV\-POOL" "3" "08/26/2015" "libsolv" "LIBSOLV"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
.\" Title: Libsolv
.\" Author: [see the "Author" section]
.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
-.\" Date: 09/20/2013
+.\" Date: 08/26/2015
.\" Manual: LIBSOLV
.\" Source: libsolv
.\" Language: English
.\"
-.TH "LIBSOLV" "3" "09/20/2013" "libsolv" "LIBSOLV"
+.TH "LIBSOLV" "3" "08/26/2015" "libsolv" "LIBSOLV"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
.\" Title: mdk2solv
.\" Author: [see the "Author" section]
.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
-.\" Date: 09/25/2014
+.\" Date: 08/26/2015
.\" Manual: LIBSOLV
.\" Source: libsolv
.\" Language: English
.\"
-.TH "MDK2SOLV" "1" "09/25/2014" "libsolv" "LIBSOLV"
+.TH "MDK2SOLV" "1" "08/26/2015" "libsolv" "LIBSOLV"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
.\" Title: mergesolv
.\" Author: [see the "Author" section]
.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
-.\" Date: 09/22/2014
+.\" Date: 08/26/2015
.\" Manual: LIBSOLV
.\" Source: libsolv
.\" Language: English
.\"
-.TH "MERGESOLV" "1" "09/22/2014" "libsolv" "LIBSOLV"
+.TH "MERGESOLV" "1" "08/26/2015" "libsolv" "LIBSOLV"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
.\" Title: repomdxml2solv
.\" Author: [see the "Author" section]
.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
-.\" Date: 09/24/2014
+.\" Date: 08/26/2015
.\" Manual: LIBSOLV
.\" Source: libsolv
.\" Language: English
.\"
-.TH "REPOMDXML2SOLV" "1" "09/24/2014" "libsolv" "LIBSOLV"
+.TH "REPOMDXML2SOLV" "1" "08/26/2015" "libsolv" "LIBSOLV"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
.\" Title: rpmdb2solv
.\" Author: [see the "Author" section]
.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
-.\" Date: 09/25/2014
+.\" Date: 08/26/2015
.\" Manual: LIBSOLV
.\" Source: libsolv
.\" Language: English
.\"
-.TH "RPMDB2SOLV" "1" "09/25/2014" "libsolv" "LIBSOLV"
+.TH "RPMDB2SOLV" "1" "08/26/2015" "libsolv" "LIBSOLV"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
.\" Title: rpmmd2solv
.\" Author: [see the "Author" section]
.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
-.\" Date: 09/24/2014
+.\" Date: 08/26/2015
.\" Manual: LIBSOLV
.\" Source: libsolv
.\" Language: English
.\"
-.TH "RPMMD2SOLV" "1" "09/24/2014" "libsolv" "LIBSOLV"
+.TH "RPMMD2SOLV" "1" "08/26/2015" "libsolv" "LIBSOLV"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
.\" Title: rpms2solv
.\" Author: [see the "Author" section]
.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
-.\" Date: 09/24/2014
+.\" Date: 08/26/2015
.\" Manual: LIBSOLV
.\" Source: libsolv
.\" Language: English
.\"
-.TH "RPMS2SOLV" "1" "09/24/2014" "libsolv" "LIBSOLV"
+.TH "RPMS2SOLV" "1" "08/26/2015" "libsolv" "LIBSOLV"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
.\" Title: susetags2solv
.\" Author: [see the "Author" section]
.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
-.\" Date: 09/24/2014
+.\" Date: 08/26/2015
.\" Manual: LIBSOLV
.\" Source: libsolv
.\" Language: English
.\"
-.TH "SUSETAGS2SOLV" "1" "09/24/2014" "libsolv" "LIBSOLV"
+.TH "SUSETAGS2SOLV" "1" "08/26/2015" "libsolv" "LIBSOLV"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
.\" Title: testsolv
.\" Author: [see the "Author" section]
.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
-.\" Date: 09/22/2014
+.\" Date: 08/26/2015
.\" Manual: LIBSOLV
.\" Source: libsolv
.\" Language: English
.\"
-.TH "TESTSOLV" "1" "09/22/2014" "libsolv" "LIBSOLV"
+.TH "TESTSOLV" "1" "08/26/2015" "libsolv" "LIBSOLV"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
.\" Title: updateinfoxml2solv
.\" Author: [see the "Author" section]
.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
-.\" Date: 09/24/2014
+.\" Date: 08/26/2015
.\" Manual: LIBSOLV
.\" Source: libsolv
.\" Language: English
.\"
-.TH "UPDATEINFOXML2SOLV" "1" "09/24/2014" "libsolv" "LIBSOLV"
+.TH "UPDATEINFOXML2SOLV" "1" "08/26/2015" "libsolv" "LIBSOLV"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
$chksum->add("1.1");
$chksum->add($cookie);
$chksum->add_fstat(fileno($f));
- my $extcookie = $chksum->raw();
- substr($extcookie, 0, 1) = chr(1) if ord(substr($extcookie, 0, 1)) == 0;
- return $extcookie;
+ return $chksum->raw();
}
sub cachepath {
$dorefresh = 0 if @s && ($self->{metadata_expire} == -1 || time() - $s[9] < $self->{metadata_expire});
}
$self->{cookie} = '';
+ $self->{extcookie} = '';
if (!$dorefresh && $self->usecachedrepo()) {
print "repo: '$self->{alias}' cached\n";
return 1;
$url =~ s!/$!!;
$url .= "/$file";
open(my $f, '+>', undef) || die;
- fcntl($f, Fcntl::F_SETFD, 0);
+ fcntl($f, Fcntl::F_SETFD, 0); # turn off CLOEXEC
my $st = system('curl', '-f', '-s', '-L', '-o', "/dev/fd/" . fileno($f), '--', $url);
if (POSIX::lseek(fileno($f), 0, POSIX::SEEK_END) == 0 && ($st == 0 || !$chksum)) {
return undef;
}
sub writecachedrepo {
- my ($self, $ext, $info) = @_;
+ my ($self, $ext, $repodata) = @_;
return if $self->{incomplete};
mkdir("/var/cache/solv", 0755) unless -d "/var/cache/solv";
my ($f, $tmpname);
return unless $f;
chmod 0444, $f;
my $ff = solv::xfopen_fd(undef, fileno($f));
- if (!$info) {
+ if (!$repodata) {
$self->{handle}->write($ff);
} elsif ($ext) {
- $info->write($ff);
+ $repodata->write($ff);
} else {
$self->{handle}->write_first_repodata($ff);
}
if ($f) {
if (!$ext) {
$self->{handle}->empty();
- die("internal error, cannot reload solv file\n") unless $self->{handle}->add_solv($f, $solv::Repo::SOLV_ADD_NO_STUBS);
+ die("internal error, cannot reload solv file\n") unless $self->{handle}->add_solv($f, $repodata ? 0 : $solv::Repo::SOLV_ADD_NO_STUBS);
} else {
- $info->extend_to_repo();
+ $repodata->extend_to_repo();
my $flags = $solv::Repo::REPO_EXTEND_SOLVABLES;
$flags |= $solv::Repo::REPO_LOCALPOOL if $ext ne 'DL';
- $info->add_solv($f, $flags);
+ $repodata->add_solv($f, $flags);
}
}
}
return '';
}
+my %langtags = (
+ $solv::SOLVABLE_SUMMARY => $solv::REPOKEY_TYPE_STR,
+ $solv::SOLVABLE_DESCRIPTION => $solv::REPOKEY_TYPE_STR,
+ $solv::SOLVABLE_EULA => $solv::REPOKEY_TYPE_STR,
+ $solv::SOLVABLE_MESSAGEINS => $solv::REPOKEY_TYPE_STR,
+ $solv::SOLVABLE_MESSAGEDEL => $solv::REPOKEY_TYPE_STR,
+ $solv::SOLVABLE_CATEGORY => $solv::REPOKEY_TYPE_ID,
+);
+
+sub add_ext_keys {
+ my ($self, $ext, $repodata, $handle) = @_;
+ if ($ext eq 'DL') {
+ $repodata->add_idarray($handle, $solv::REPOSITORY_KEYS, $solv::REPOSITORY_DELTAINFO);
+ $repodata->add_idarray($handle, $solv::REPOSITORY_KEYS, $solv::REPOKEY_TYPE_FLEXARRAY);
+ } elsif ($ext eq 'DU') {
+ $repodata->add_idarray($handle, $solv::REPOSITORY_KEYS, $solv::SOLVABLE_DISKUSAGE);
+ $repodata->add_idarray($handle, $solv::REPOSITORY_KEYS, $solv::REPOKEY_TYPE_DIRNUMNUMARRAY);
+ } elsif ($ext eq 'FL') {
+ $repodata->add_idarray($handle, $solv::REPOSITORY_KEYS, $solv::SOLVABLE_FILELIST);
+ $repodata->add_idarray($handle, $solv::REPOSITORY_KEYS, $solv::REPOKEY_TYPE_DIRSTRARRAY);
+ } else {
+ for my $langid (sort { $a <=> $b } keys %langtags) {
+ $repodata->add_idarray($handle, $solv::REPOSITORY_KEYS, $self->{handle}->{pool}->id2langid($langid, $ext, 1));
+ $repodata->add_idarray($handle, $solv::REPOSITORY_KEYS, $langtags{$langid});
+ }
+ }
+}
+
package Repo::rpmmd;
our @ISA = ('Repo::generic');
$repodata->set_poolstr($handle, $solv::REPOSITORY_REPOMD_TYPE, $what);
$repodata->set_str($handle, $solv::REPOSITORY_REPOMD_LOCATION, $filename);
$repodata->set_checksum($handle, $solv::REPOSITORY_REPOMD_CHECKSUM, $chksum);
- if ($ext eq 'DL') {
- $repodata->add_idarray($handle, $solv::REPOSITORY_KEYS, $solv::REPOSITORY_DELTAINFO);
- $repodata->add_idarray($handle, $solv::REPOSITORY_KEYS, $solv::REPOKEY_TYPE_FLEXARRAY);
- } elsif ($ext eq 'FL') {
- $repodata->add_idarray($handle, $solv::REPOSITORY_KEYS, $solv::SOLVABLE_FILELIST);
- $repodata->add_idarray($handle, $solv::REPOSITORY_KEYS, $solv::REPOKEY_TYPE_DIRSTRARRAY);
- }
+ $self->add_ext_keys($ext, $repodata, $handle);
$repodata->add_flexarray($solv::SOLVID_META, $solv::REPOSITORY_EXTERNAL, $handle);
}
return (undef, undef);
}
-my %langtags = (
- $solv::SOLVABLE_SUMMARY => $solv::REPOKEY_TYPE_STR,
- $solv::SOLVABLE_DESCRIPTION => $solv::REPOKEY_TYPE_STR,
- $solv::SOLVABLE_EULA => $solv::REPOKEY_TYPE_STR,
- $solv::SOLVABLE_MESSAGEINS => $solv::REPOKEY_TYPE_STR,
- $solv::SOLVABLE_MESSAGEDEL => $solv::REPOKEY_TYPE_STR,
- $solv::SOLVABLE_CATEGORY => $solv::REPOKEY_TYPE_ID,
-);
sub add_ext {
my ($self, $repodata, $what, $ext) = @_;
my ($filename, $chksum) = $self->find($what);
+ return unless $filename;
my $handle = $repodata->new_handle();
$repodata->set_str($handle, $solv::SUSETAGS_FILE_NAME, $filename);
$repodata->set_checksum($handle, $solv::SUSETAGS_FILE_CHECKSUM, $chksum);
- if ($ext eq 'DL') {
- $repodata->add_idarray($handle, $solv::REPOSITORY_KEYS, $solv::REPOSITORY_DELTAINFO);
- $repodata->add_idarray($handle, $solv::REPOSITORY_KEYS, $solv::REPOKEY_TYPE_FLEXARRAY);
- } elsif ($ext eq 'DU') {
- $repodata->add_idarray($handle, $solv::REPOSITORY_KEYS, $solv::SOLVABLE_DISKUSAGE);
- $repodata->add_idarray($handle, $solv::REPOSITORY_KEYS, $solv::REPOKEY_TYPE_DIRNUMNUMARRAY);
- } elsif ($ext eq 'FL') {
- $repodata->add_idarray($handle, $solv::REPOSITORY_KEYS, $solv::SOLVABLE_FILELIST);
- $repodata->add_idarray($handle, $solv::REPOSITORY_KEYS, $solv::REPOKEY_TYPE_DIRSTRARRAY);
- } else {
- for my $langid (sort { $a <=> $b } keys %langtags) {
- $repodata->add_idarray($handle, $solv::REPOSITORY_KEYS, $self->{handle}->{pool}->id2langid($langid, $ext, 1));
- $repodata->add_idarray($handle, $solv::REPOSITORY_KEYS, $langtags{$langid});
- }
- }
+ $self->add_ext_keys($ext, $repodata, $handle);
$repodata->add_flexarray($solv::SOLVID_META, $solv::REPOSITORY_EXTERNAL, $handle);
}
if (@newpkgs) {
my $downloadsize = 0;
$downloadsize += $_->lookup_num($solv::SOLVABLE_DOWNLOADSIZE) for @newpkgs;
- printf "Downloading %d packages, %d K\n", scalar(@newpkgs), $downloadsize;
+ printf "Downloading %d packages, %d K\n", scalar(@newpkgs), $downloadsize / 1024;
for my $p (@newpkgs) {
my $repo = $p->{repo}->{appdata};
my ($location) = $p->lookup_location();
print "install ".$p->str()."\n";
my $f = $newpkgsfps{$p->{id}};
my $mode = $steptype == $solv::Transaction::SOLVER_TRANSACTION_INSTALL ? '-U' : '-i';
+ $f->cloexec(0);
system('rpm', $mode, '--force', '--nodeps', '--nodigest', '--nosignature', "/dev/fd/".$f->fileno()) && die("rpm failed: $?\n");
delete $newpkgsfps{$p->{id}};
}
chksum.add("1.1");
chksum.add(cookie)
chksum.add_fstat(f.fileno())
- extcookie = chksum.raw()
- if sys.version > '3':
- # compatibility to c code
- if extcookie[0] == 0:
- extcookie[0] = 1
- else:
- # compatibility to c code
- if ord(extcookie[0]) == 0:
- extcookie[0] = chr(1)
- return extcookie
+ return chksum.raw()
def cachepath(self, ext = None):
path = re.sub(r'^\.', '_', self.name)
except OSError:
pass
self['cookie'] = ''
+ self['extcookie'] = ''
if not dorefresh and self.usecachedrepo(None):
print("repo: '%s': cached" % self.name)
return True
return False
return True
- def writecachedrepo(self, ext, info=None):
+ def writecachedrepo(self, ext, repodata=None):
if 'incomplete' in self:
return
tmpname = None
os.fchmod(fd, 0o444)
f = os.fdopen(fd, 'wb+')
f = solv.xfopen_fd(None, f.fileno())
- if not info:
+ if not repodata:
self.handle.write(f)
elif ext:
- info.write(f)
- else: # rewrite_repos case
+ repodata.write(f)
+ else: # rewrite_repos case, do not write stubs
self.handle.write_first_repodata(f)
f.flush()
if self.type != 'system' and not ext:
- if 'extcookie' not in self:
+ if not self['extcookie']:
self['extcookie'] = self.calc_cookie_ext(f, self['cookie'])
- os.write(f.fileno(), self['extcookie'])
+ f.write(self['extcookie'])
if not ext:
- os.write(f.fileno(), self['cookie'])
+ f.write(self['cookie'])
else:
- os.write(f.fileno(), self['extcookie'])
+ f.write(self['extcookie'])
f.close
if self.handle.iscontiguous():
# switch to saved repo to activate paging and save memory
if not ext:
# main repo
self.handle.empty()
- if not self.handle.add_solv(nf, solv.Repo.SOLV_ADD_NO_STUBS):
+ flags = solv.Repo.SOLV_ADD_NO_STUBS
+ if repodata:
+ flags = 0 # rewrite repos case, recreate stubs
+ if not self.handle.add_solv(nf, flags):
sys.exit("internal error, cannot reload solv file")
else:
# extension repodata
# need to extend to repo boundaries, as this is how
- # info.write() has written the data
- info.extend_to_repo()
+ # repodata.write() has written the data
+ repodata.extend_to_repo()
flags = solv.Repo.REPO_EXTEND_SOLVABLES
if ext != 'DL':
flags |= solv.Repo.REPO_LOCALPOOL
- info.add_solv(nf, flags)
+ repodata.add_solv(nf, flags)
os.rename(tmpname, self.cachepath(ext))
except (OSError, IOError):
if tmpname:
def packagespath(self):
return ''
+ def add_ext_keys(self, ext, repodata, handle):
+ if ext == 'DL':
+ repodata.add_idarray(handle, solv.REPOSITORY_KEYS, solv.REPOSITORY_DELTAINFO)
+ repodata.add_idarray(handle, solv.REPOSITORY_KEYS, solv.REPOKEY_TYPE_FLEXARRAY)
+ elif ext == 'DU':
+ repodata.add_idarray(handle, solv.REPOSITORY_KEYS, solv.SOLVABLE_DISKUSAGE)
+ repodata.add_idarray(handle, solv.REPOSITORY_KEYS, solv.REPOKEY_TYPE_DIRNUMNUMARRAY)
+ elif ext == 'FL':
+ repodata.add_idarray(handle, solv.REPOSITORY_KEYS, solv.SOLVABLE_FILELIST)
+ repodata.add_idarray(handle, solv.REPOSITORY_KEYS, solv.REPOKEY_TYPE_DIRSTRARRAY)
+ else:
+ for langtag, langtagtype in [
+ (solv.SOLVABLE_SUMMARY, solv.REPOKEY_TYPE_STR),
+ (solv.SOLVABLE_DESCRIPTION, solv.REPOKEY_TYPE_STR),
+ (solv.SOLVABLE_EULA, solv.REPOKEY_TYPE_STR),
+ (solv.SOLVABLE_MESSAGEINS, solv.REPOKEY_TYPE_STR),
+ (solv.SOLVABLE_MESSAGEDEL, solv.REPOKEY_TYPE_STR),
+ (solv.SOLVABLE_CATEGORY, solv.REPOKEY_TYPE_ID)
+ ]:
+ repodata.add_idarray(handle, solv.REPOSITORY_KEYS, self.handle.pool.id2langid(langtag, ext, 1))
+ repodata.add_idarray(handle, solv.REPOSITORY_KEYS, langtagtype)
+
+
class repo_repomd(repo_generic):
def load(self, pool):
if super(repo_repomd, self).load(pool):
repodata.set_poolstr(handle, solv.REPOSITORY_REPOMD_TYPE, what)
repodata.set_str(handle, solv.REPOSITORY_REPOMD_LOCATION, filename)
repodata.set_checksum(handle, solv.REPOSITORY_REPOMD_CHECKSUM, chksum)
- if ext == 'DL':
- repodata.add_idarray(handle, solv.REPOSITORY_KEYS, solv.REPOSITORY_DELTAINFO)
- repodata.add_idarray(handle, solv.REPOSITORY_KEYS, solv.REPOKEY_TYPE_FLEXARRAY)
- elif ext == 'FL':
- repodata.add_idarray(handle, solv.REPOSITORY_KEYS, solv.SOLVABLE_FILELIST)
- repodata.add_idarray(handle, solv.REPOSITORY_KEYS, solv.REPOKEY_TYPE_DIRSTRARRAY)
+ self.add_ext_keys(ext, repodata, handle)
repodata.add_flexarray(solv.SOLVID_META, solv.REPOSITORY_EXTERNAL, handle)
def add_exts(self):
repodata.set_str(handle, solv.SUSETAGS_FILE_NAME, filename)
if chksum:
repodata.set_checksum(handle, solv.SUSETAGS_FILE_CHECKSUM, chksum)
- if ext == 'DU':
- repodata.add_idarray(handle, solv.REPOSITORY_KEYS, solv.SOLVABLE_DISKUSAGE)
- repodata.add_idarray(handle, solv.REPOSITORY_KEYS, solv.REPOKEY_TYPE_DIRNUMNUMARRAY)
- elif ext == 'FL':
- repodata.add_idarray(handle, solv.REPOSITORY_KEYS, solv.SOLVABLE_FILELIST)
- repodata.add_idarray(handle, solv.REPOSITORY_KEYS, solv.REPOKEY_TYPE_DIRSTRARRAY)
- else:
- for langtag, langtagtype in [
- (solv.SOLVABLE_SUMMARY, solv.REPOKEY_TYPE_STR),
- (solv.SOLVABLE_DESCRIPTION, solv.REPOKEY_TYPE_STR),
- (solv.SOLVABLE_EULA, solv.REPOKEY_TYPE_STR),
- (solv.SOLVABLE_MESSAGEINS, solv.REPOKEY_TYPE_STR),
- (solv.SOLVABLE_MESSAGEDEL, solv.REPOKEY_TYPE_STR),
- (solv.SOLVABLE_CATEGORY, solv.REPOKEY_TYPE_ID)
- ]:
- repodata.add_idarray(handle, solv.REPOSITORY_KEYS, self.handle.pool.id2langid(langtag, ext, 1))
- repodata.add_idarray(handle, solv.REPOSITORY_KEYS, langtagtype)
+ self.add_ext_keys(ext, repodata, handle)
repodata.add_flexarray(solv.SOLVID_META, solv.REPOSITORY_EXTERNAL, handle)
def add_exts(self):
downloadsize = 0
for p in newpkgs:
downloadsize += p.lookup_num(solv.SOLVABLE_DOWNLOADSIZE)
- print("Downloading %d packages, %d K" % (len(newpkgs), downloadsize))
+ print("Downloading %d packages, %d K" % (len(newpkgs), downloadsize / 1024))
for p in newpkgs:
repo = p.repo.appdata
location, medianr = p.lookup_location()
continue
if not sysrepo.handle.isempty() and os.access('/usr/bin/applydeltarpm', os.X_OK):
pname = p.name
- di = p.repo.Dataiterator(solv.SOLVID_META, solv.DELTA_PACKAGE_NAME, pname, solv.Dataiterator.SEARCH_STRING)
+ di = p.repo.Dataiterator_meta(solv.DELTA_PACKAGE_NAME, pname, solv.Dataiterator.SEARCH_STRING)
di.prepend_keyname(solv.REPOSITORY_DELTAINFO)
for d in di:
dp = d.parentpos()
continue
nf = tempfile.TemporaryFile()
nf = os.dup(nf.fileno()) # get rid of CLOEXEC
+ f.cloexec(0)
st = subprocess.call(['/usr/bin/applydeltarpm', '-a', p.arch, "/dev/fd/%d" % f.fileno(), "/dev/fd/%d" % nf])
if st:
os.close(nf)
chksum.add("1.1")
chksum.add(cookie)
chksum.add_fstat(f.fileno)
- extcookie = chksum.raw()
- extcookie[0] = 1 if extcookie[0] == 0
- return extcookie
+ return chksum.raw()
end
def cachepath(ext = nil)
end
end
@cookie = nil
+ @extcookie = nil
if !dorefresh && usecachedrepo(nil)
puts "repo: '#{@name}' cached"
return true
return true
end
- def writecachedrepo(ext, info = nil)
+ def writecachedrepo(ext, repodata = nil)
return if @incomplete
begin
Dir::mkdir("/var/cache/solv", 0755) unless FileTest.directory?("/var/cache/solv")
f = Tempfile.new('.newsolv-', '/var/cache/solv')
f.chmod(0444)
sf = Solv::xfopen_fd('', f.fileno)
- if !info
+ if !repodata
@handle.write(sf)
elsif ext
- info.write(sf)
+ repodata.write(sf)
else
@handle.write_first_repodata(sf)
end
if sf
if !ext
@handle.empty()
- abort("internal error, cannot reload solv file") unless @handle.add_solv(sf, Solv::Repo::SOLV_ADD_NO_STUBS)
+ abort("internal error, cannot reload solv file") unless @handle.add_solv(sf, repodata ? 0 : Solv::Repo::SOLV_ADD_NO_STUBS)
else
- info.extend_to_repo()
+ repodata.extend_to_repo()
flags = Solv::Repo::REPO_EXTEND_SOLVABLES
flags |= Solv::Repo::REPO_LOCALPOOL if ext != 'DL'
- info.add_solv(sf, flags)
+ repodata.add_solv(sf, flags)
end
sf.close
end
def packagespath()
return ''
end
+
+ @@langtags = {
+ Solv::SOLVABLE_SUMMARY => Solv::REPOKEY_TYPE_STR,
+ Solv::SOLVABLE_DESCRIPTION => Solv::REPOKEY_TYPE_STR,
+ Solv::SOLVABLE_EULA => Solv::REPOKEY_TYPE_STR,
+ Solv::SOLVABLE_MESSAGEINS => Solv::REPOKEY_TYPE_STR,
+ Solv::SOLVABLE_MESSAGEDEL => Solv::REPOKEY_TYPE_STR,
+ Solv::SOLVABLE_CATEGORY => Solv::REPOKEY_TYPE_ID,
+ }
+
+ def add_ext_keys(ext, repodata, h)
+ if ext == 'DL'
+ repodata.add_idarray(h, Solv::REPOSITORY_KEYS, Solv::REPOSITORY_DELTAINFO)
+ repodata.add_idarray(h, Solv::REPOSITORY_KEYS, Solv::REPOKEY_TYPE_FLEXARRAY)
+ elsif ext == 'DU'
+ repodata.add_idarray(h, Solv::REPOSITORY_KEYS, Solv::SOLVABLE_DISKUSAGE)
+ repodata.add_idarray(h, Solv::REPOSITORY_KEYS, Solv::REPOKEY_TYPE_DIRNUMNUMARRAY)
+ elsif ext == 'FL'
+ repodata.add_idarray(h, Solv::REPOSITORY_KEYS, Solv::SOLVABLE_FILELIST)
+ repodata.add_idarray(h, Solv::REPOSITORY_KEYS, Solv::REPOKEY_TYPE_DIRSTRARRAY)
+ else
+ @@langtags.sort.each do |langid, langtype|
+ repodata.add_idarray(h, Solv::REPOSITORY_KEYS, @handle.pool.id2langid(langid, ext, true))
+ repodata.add_idarray(h, Solv::REPOSITORY_KEYS, langtype)
+ end
+ end
+ end
end
class Repo_rpmmd < Repo_generic
repodata.set_poolstr(h, Solv::REPOSITORY_REPOMD_TYPE, what)
repodata.set_str(h, Solv::REPOSITORY_REPOMD_LOCATION, filename)
repodata.set_checksum(h, Solv::REPOSITORY_REPOMD_CHECKSUM, filechksum)
- if ext == 'DL'
- repodata.add_idarray(h, Solv::REPOSITORY_KEYS, Solv::REPOSITORY_DELTAINFO)
- repodata.add_idarray(h, Solv::REPOSITORY_KEYS, Solv::REPOKEY_TYPE_FLEXARRAY)
- elsif ext == 'FL'
- repodata.add_idarray(h, Solv::REPOSITORY_KEYS, Solv::SOLVABLE_FILELIST)
- repodata.add_idarray(h, Solv::REPOSITORY_KEYS, Solv::REPOKEY_TYPE_DIRSTRARRAY)
- end
+ add_ext_keys(ext, repodata, h)
repodata.add_flexarray(Solv::SOLVID_META, Solv::REPOSITORY_EXTERNAL, h)
end
return true
end
- @@langtags = {
- Solv::SOLVABLE_SUMMARY => Solv::REPOKEY_TYPE_STR,
- Solv::SOLVABLE_DESCRIPTION => Solv::REPOKEY_TYPE_STR,
- Solv::SOLVABLE_EULA => Solv::REPOKEY_TYPE_STR,
- Solv::SOLVABLE_MESSAGEINS => Solv::REPOKEY_TYPE_STR,
- Solv::SOLVABLE_MESSAGEDEL => Solv::REPOKEY_TYPE_STR,
- Solv::SOLVABLE_CATEGORY => Solv::REPOKEY_TYPE_ID,
- }
-
def add_ext(repodata, what, ext)
(filename, filechksum) = find(what)
h = repodata.new_handle()
repodata.set_str(h, Solv::SUSETAGS_FILE_NAME, filename)
repodata.set_checksum(h, Solv::SUSETAGS_FILE_CHECKSUM, filechksum)
- if ext == 'DL'
- repodata.add_idarray(h, Solv::REPOSITORY_KEYS, Solv::REPOSITORY_DELTAINFO)
- repodata.add_idarray(h, Solv::REPOSITORY_KEYS, Solv::REPOKEY_TYPE_FLEXARRAY)
- elsif ext == 'DU'
- repodata.add_idarray(h, Solv::REPOSITORY_KEYS, Solv::SOLVABLE_DISKUSAGE)
- repodata.add_idarray(h, Solv::REPOSITORY_KEYS, Solv::REPOKEY_TYPE_DIRNUMNUMARRAY)
- elsif ext == 'FL'
- repodata.add_idarray(h, Solv::REPOSITORY_KEYS, Solv::SOLVABLE_FILELIST)
- repodata.add_idarray(h, Solv::REPOSITORY_KEYS, Solv::REPOKEY_TYPE_DIRSTRARRAY)
- else
- @@langtags.sort.each do |langid, langtype|
- repodata.add_idarray(h, Solv::REPOSITORY_KEYS, @handle.pool.id2langid(langid, ext, true))
- repodata.add_idarray(h, Solv::REPOSITORY_KEYS, langtype)
- end
- end
+ add_ext_keys(ext, repodata, h)
repodata.add_flexarray(Solv::SOLVID_META, Solv::REPOSITORY_EXTERNAL, h)
end
end
f = Solv::xfopen(cachepath())
@handle.add_rpmdb_reffp(f, Solv::Repo::REPO_REUSE_REPODATA)
- f.close
+ f.close if f
writecachedrepo(nil)
return true
end
for p in newpkgs
downloadsize += p.lookup_num(Solv::SOLVABLE_DOWNLOADSIZE)
end
- puts "Downloading #{newpkgs.length} packages, #{downloadsize} K"
+ puts "Downloading #{newpkgs.length} packages, #{downloadsize / 1024} K"
for p in newpkgs
repo = p.repo.appdata
location, medianr = p.lookup_location()
f = newpkgsfp.delete(p.id)
next unless f
mode = steptype == Solv::Transaction::SOLVER_TRANSACTION_INSTALL ? '-U' : '-i'
+ f.cloexec(0)
system('rpm', mode, '--force', '--nodeps', '--nodigest', '--nosignature', "/dev/fd/#{f.fileno().to_s}") || abort("rpm failed: #{$? >> 8}")
f.close
end
int metadata_expire;
char **components;
int ncomponents;
-
unsigned char cookie[32];
+ int extcookieset;
unsigned char extcookie[32];
int incomplete;
};
fclose(fp);
return 0;
}
- if (cookie && memcmp(cookie, mycookie, sizeof(mycookie)))
+ if (cookie && memcmp(cookie, mycookie, sizeof(mycookie)) != 0)
{
fclose(fp);
return 0;
{
memcpy(cinfo->cookie, mycookie, sizeof(mycookie));
memcpy(cinfo->extcookie, myextcookie, sizeof(myextcookie));
+ cinfo->extcookieset = 1;
}
if (mark)
futimens(fileno(fp), 0); /* try to set modification time */
}
void
-writecachedrepo(Repo *repo, Repodata *info, const char *repoext, unsigned char *cookie)
+writecachedrepo(Repo *repo, Repodata *repodata, const char *repoext, unsigned char *cookie)
{
FILE *fp;
int i, fd;
if (i < repo->end)
onepiece = 0;
- if (!info)
+ if (!repodata)
repo_write(repo, fp);
else if (repoext)
- repodata_write(info, fp);
+ repodata_write(repodata, fp);
else
{
int oldnrepodata = repo->nrepodata;
repo->nrepodata = oldnrepodata > 2 ? 2 : oldnrepodata; /* XXX: do this right */
repo_write(repo, fp);
repo->nrepodata = oldnrepodata;
- onepiece = 0;
+ onepiece = 0; /* don't bother for the added file provides */
}
if (!repoext && cinfo)
{
- if (!cinfo->extcookie[0])
+ if (!cinfo->extcookieset)
{
/* create the ext cookie and append it */
/* we just need some unique ID */
if (!fstat(fileno(fp), &stb))
memset(&stb, 0, sizeof(stb));
calc_checksum_stat(&stb, REPOKEY_TYPE_SHA256, cookie, cinfo->extcookie);
- if (cinfo->extcookie[0] == 0)
- cinfo->extcookie[0] = 1;
+ cinfo->extcookieset = 1;
}
if (fwrite(cinfo->extcookie, 32, 1, fp) != 1)
{
int flags = REPO_USE_LOADING|REPO_EXTEND_SOLVABLES;
/* make sure repodata contains complete repo */
/* (this is how repodata_write saves it) */
- repodata_extend_block(info, repo->start, repo->end - repo->start);
- info->state = REPODATA_LOADING;
+ repodata_extend_block(repodata, repo->start, repo->end - repo->start);
+ repodata->state = REPODATA_LOADING;
if (strcmp(repoext, "DL") != 0)
flags |= REPO_LOCALPOOL;
repo_add_solv(repo, fp, flags);
- info->state = REPODATA_AVAILABLE; /* in case the load failed */
+ repodata->state = REPODATA_AVAILABLE; /* in case the load failed */
}
fclose(fp);
}
printf("%s\n", pool_errstr(repo->pool));
return 0;
}
- writecachedrepo(repo, data, ext, cinfo->extcookie);
+ if (cinfo->extcookieset)
+ writecachedrepo(repo, data, ext, cinfo->extcookie);
return 1;
}
return 0;
}
fclose(fp);
- writecachedrepo(repo, data, ext, cinfo->extcookie);
+ if (cinfo->extcookieset)
+ writecachedrepo(repo, data, ext, cinfo->extcookie);
return 1;
}
#endif
--- /dev/null
+#!/usr/bin/tclsh
+
+package require solv
+package require inifile
+package require fileutil
+
+set reposdir /etc/zypp/repos.d
+
+### some helpers
+
+proc fileno {file} {
+ if [regexp -- {^file(\d+)$} $file match fd] {
+ return $fd
+ }
+ error "file not open"
+}
+
+set ::globalarray_cnt 0
+
+proc globalarray {} {
+ set name "::globalarray_[incr ::globalarray_cnt]"
+ array set $name [list varName $name]
+ return $name
+}
+
+### generic repo handling (cache reading/writing)
+
+proc repo_calc_cookie_file {selfName filename} {
+ upvar $selfName self
+ set chksum [solv::new_Chksum $solv::REPOKEY_TYPE_SHA256]
+ $chksum add "1.1"
+ $chksum add_stat $filename
+ return [$chksum raw]
+}
+
+proc repo_calc_cookie_fp {selfName fp} {
+ upvar $selfName self
+ set chksum [solv::new_Chksum $solv::REPOKEY_TYPE_SHA256]
+ $chksum add "1.1"
+ $chksum add_fp $fp
+ return [$chksum raw]
+}
+
+proc repo_calc_cookie_ext {selfName f cookie} {
+ upvar $selfName self
+ set chksum [solv::new_Chksum $solv::REPOKEY_TYPE_SHA256]
+ $chksum add "1.1"
+ $chksum add $cookie
+ $chksum add_fstat [$f fileno]
+ return [$chksum raw]
+}
+
+proc repo_cachepath {selfName {ext "-"}} {
+ upvar $selfName self
+ regsub {^\.} $self(name) _ path
+ if {$ext ne "-"} {
+ set path "${path}_$ext.solvx"
+ } else {
+ set path "${path}.solv"
+ }
+ regsub -all / $path _ path
+ return "/var/cache/solv/$path"
+}
+
+proc repo_generic_load {selfName pool} {
+ upvar $selfName self
+ set handle [ $pool add_repo $self(name) ]
+ set self(handle) $handle
+ $handle configure -priority [expr 99 - $self(priority)] -appdata $self(varName)
+ set dorefresh $self(autorefresh)
+ set metadata_expire $self(metadata_expire)
+ catch {
+ if {$metadata_expire == -1 || [clock seconds] - [file mtime [repo_cachepath self]] < $metadata_expire} {
+ set dorefresh 0
+ }
+ }
+ set self(cookie) {}
+ set self(extcookie) {}
+ if { !$dorefresh && [repo_usecachedrepo self] } {
+ puts "repo $self(name): cached"
+ return 1
+ }
+ return 0
+}
+
+proc repo_free_handle {selfName} {
+ upvar $selfName self
+ set handle $self(handle)
+ unset self(handle)
+ $handle free 1
+}
+
+proc repo_usecachedrepo {selfName {ext "-"} {mark 0}} {
+ upvar $selfName self
+ set repopath [repo_cachepath self $ext]
+ set code [catch {
+ set f [open $repopath "rb"]
+ seek $f -32 end
+ set fcookie [read $f 32]
+ set cookie [expr {$ext eq "-" ? $self(cookie) : $self(extcookie)}]
+ if {$cookie ne {} && $cookie ne $fcookie} {
+ close $f
+ return 0
+ }
+ set fextcookie {}
+ if {$ext eq "-" && $self(type) ne "system"} {
+ seek $f -64 end
+ set fextcookie [read $f 32]
+ }
+ seek $f 0 start
+ set ff [solv::xfopen_fd {} [fileno $f]]
+ close $f
+ set flags 0
+ if {$ext ne "-"} {
+ set flags [expr $solv::Repo_REPO_USE_LOADING | $solv::Repo_REPO_EXTEND_SOLVABLES]
+ if {$ext ne "DL"} {
+ set flags [expr $flags | $solv::Repo_REPO_LOCALPOOL]
+ }
+ }
+ if {! [$self(handle) add_solv $ff $flags]} {
+ $ff close
+ return 0
+ }
+ $ff close
+ if {$self(type) ne "system" && $ext eq "-"} {
+ set self(cookie) $fcookie
+ set self(extcookie) $fextcookie
+ }
+ if {$mark} {
+ catch {
+ ::fileutil::touch -c -m -t [clock seconds] $repopath
+ }
+ }
+ return 1
+ } res]
+ return [expr {$code == 2 ? $res : 0}]
+}
+
+proc repo_writecachedrepo {selfName {ext "-"} {repodata "NULL"}} {
+ upvar $selfName self
+ if [info exists self(incomplete)] {
+ return
+ }
+ file mkdir "/var/cache/solv"
+ ::fileutil::tempdir "/var/cache/solv"
+ set tempfilename [::fileutil::tempfile ".newsolv-"]
+ ::fileutil::tempdirReset
+ set f [solv::xfopen $tempfilename "w+"]
+ file attributes $tempfilename -permissions 0444
+ if {$repodata eq {NULL}} {
+ $self(handle) write $f
+ } else {
+ $repodata write $f
+ }
+ $f flush
+ if {$self(type) ne "system" && $ext eq "-"} {
+ if {$self(extcookie) eq {}} {
+ set self(extcookie) [repo_calc_cookie_ext self $f $self(cookie)]
+ }
+ $f write $self(extcookie)
+ }
+ $f write [expr {$ext eq "-" ? $self(cookie) : $self(extcookie)}]
+ $f close
+ file rename -force -- $tempfilename [repo_cachepath self $ext]
+}
+
+proc repo_download {selfName file uncompress chksum {markincomplete 0}} {
+ upvar $selfName self
+ regsub {/$} $self(baseurl) {} url
+ set url "$url/$file"
+ set tempfilename [::fileutil::tempfile]
+ set f [open $tempfilename rb+]
+ file delete -- $tempfilename
+ if [catch {
+ exec -ignorestderr -- curl -f -s -L $url ">@$f"
+ }] {
+ seek $f 0 end
+ if {($chksum ne "" && $chksum ne "NULL") || [tell $f] != 0} {
+ puts "$file: download error"
+ }
+ close $f
+ return {NULL}
+ }
+ seek $f 0 start
+ if {$chksum ne "" && $chksum ne "NULL"} {
+ set fchksum [solv::new_Chksum [$chksum cget -type]]
+ if {$fchksum eq "" || $fchksum eq "NULL"} {
+ puts "$file: unknown checksum type"
+ if {$markincomplete} {
+ set self(incomplete) 1
+ }
+ close $f
+ return {NULL}
+ }
+ $fchksum add_fd [fileno $f]
+ if {[$fchksum != $chksum]} {
+ puts "$file: checksum mismatch"
+ if {$markincomplete} {
+ set self(incomplete) 1
+ }
+ close $f
+ return {NULL}
+ }
+ }
+ set ff [solv::xfopen_fd [expr {$uncompress ? $file : ""}] [fileno $f]]
+ close $f
+ return $ff
+}
+
+proc repo_generic_add_ext_keys {selfName ext repodata h} {
+ upvar $selfName self
+ if {$ext eq "DL"} {
+ $repodata add_idarray $h $solv::REPOSITORY_KEYS $solv::REPOSITORY_DELTAINFO
+ $repodata add_idarray $h $solv::REPOSITORY_KEYS $solv::REPOKEY_TYPE_FLEXARRAY
+ } elseif {$ext eq "DU"} {
+ $repodata add_idarray $h $solv::REPOSITORY_KEYS $solv::SOLVABLE_DISKUSAGE
+ $repodata add_idarray $h $solv::REPOSITORY_KEYS $solv::REPOKEY_TYPE_DIRNUMNUMARRAY
+ } elseif {$ext eq "FL"} {
+ $repodata add_idarray $h $solv::REPOSITORY_KEYS $solv::SOLVABLE_FILELIST
+ $repodata add_idarray $h $solv::REPOSITORY_KEYS $solv::REPOKEY_TYPE_DIRSTRARRAY
+ }
+}
+
+### system
+
+proc repo_system_load {selfName pool} {
+ upvar $selfName self
+ set handle [ $pool add_repo $self(name) ]
+ set self(handle) $handle
+ $handle configure -appdata $self(varName)
+ $pool configure -installed $handle
+ puts -nonewline "rpm database: "
+ set self(cookie) [repo_calc_cookie_file self "/var/lib/rpm/Packages"]
+ if [repo_usecachedrepo self] {
+ puts "cached"
+ return 1
+ }
+ puts "reading"
+ set f [solv::xfopen [repo_cachepath self]]
+ $handle add_rpmdb_reffp $f $solv::Repo_REPO_REUSE_REPODATA
+ repo_writecachedrepo self
+}
+
+### repomd
+
+proc repo_repomd_add_ext {selfName repodata what ext} {
+ upvar $selfName self
+ set where [repo_repomd_find self $what]
+ if {$where eq {}} {
+ return
+ }
+ set h [$repodata new_handle]
+ $repodata set_poolstr $h $solv::REPOSITORY_REPOMD_TYPE $what
+ $repodata set_str $h $solv::REPOSITORY_REPOMD_LOCATION [lindex $where 0]
+ $repodata set_checksum $h $solv::REPOSITORY_REPOMD_CHECKSUM [lindex $where 1]
+ repo_generic_add_ext_keys self $ext $repodata $h
+ $repodata add_flexarray $solv::SOLVID_META $solv::REPOSITORY_EXTERNAL $h
+}
+
+proc repo_repomd_add_exts {selfName} {
+ upvar $selfName self
+ set repodata [$self(handle) add_repodata 0]
+ repo_repomd_add_ext self $repodata "filelists" "FL"
+ $repodata internalize
+}
+
+proc repo_repomd_find {selfName what} {
+ upvar $selfName self
+ set di [$self(handle) Dataiterator_meta $solv::REPOSITORY_REPOMD_TYPE $what $solv::Dataiterator_SEARCH_STRING]
+ $di prepend_keyname $solv::REPOSITORY_REPOMD
+ solv::iter d $di {
+ set dp [$d parentpos]
+ set filename [$dp lookup_str $solv::REPOSITORY_REPOMD_LOCATION]
+ set checksum [$dp lookup_checksum $solv::REPOSITORY_REPOMD_CHECKSUM]
+ if {$filename ne "" && $checksum eq "NULL"} {
+ puts "no $filename file checksum"
+ } elseif {$filename ne ""} {
+ return [list $filename $checksum]
+ }
+ }
+ return {}
+}
+
+proc repo_repomd_load {selfName pool} {
+ upvar $selfName self
+ if [repo_generic_load self $pool] {
+ return 1
+ }
+ puts -nonewline "rpmmd repo '$self(name)': "
+ set f [repo_download self {repodata/repomd.xml} 0 {}]
+ if {$f eq {NULL}} {
+ puts "no repomd.xml file, skipped"
+ repo_free_handle self
+ return 0
+ }
+ set self(cookie) [repo_calc_cookie_fp self $f]
+ if [repo_usecachedrepo self "-" 1] {
+ puts "cached"
+ return 1
+ }
+ set handle $self(handle)
+ $handle add_repomdxml $f
+ puts "fetching"
+ set primary [repo_repomd_find self primary]
+ if {$primary ne {}} {
+ set f [repo_download self [lindex $primary 0] 1 [lindex $primary 1] 1]
+ if {$f ne {NULL}} {
+ $handle add_rpmmd $f {}
+ $f close
+ }
+ if [info exists self(incomplete)] {
+ return 0
+ }
+ }
+ set updateinfo [repo_repomd_find self primary]
+ if {$updateinfo ne {}} {
+ set f [repo_download self [lindex $updateinfo 0] 1 [lindex $updateinfo 1] 1]
+ if {$f ne {NULL}} {
+ $handle add_updateinfoxml $f
+ $f close
+ }
+ }
+ repo_repomd_add_exts self
+ repo_writecachedrepo self
+ $self(handle) create_stubs
+ return 1
+}
+
+proc repo_repomd_packagespath {selfName} {
+ return ""
+}
+
+proc repo_repomd_load_ext {selfName repodata} {
+ upvar $selfName self
+ switch -- [$repodata lookup_str $solv::SOLVID_META $solv::REPOSITORY_REPOMD_TYPE] {
+ "deltainfo" {
+ set ext DL
+ }
+ "filelists" {
+ set ext FL
+ }
+ default {
+ return 0
+ }
+ }
+ puts -nonewline "\[$self(name):$ext: "
+ flush stdout
+ if [repo_usecachedrepo self $ext] {
+ puts "cached]"
+ return 1
+ }
+ puts "fetching]"
+ set handle $self(handle)
+ set filename [$repodata lookup_str $solv::SOLVID_META $solv::REPOSITORY_REPOMD_LOCATION]
+ set filechecksum [$repodata lookup_checksum $solv::SOLVID_META $solv::REPOSITORY_REPOMD_CHECKSUM]
+ set f [repo_download self $filename 1 $filechecksum]
+ if {$f eq {NULL}} {
+ return 0
+ }
+ if {$ext eq "FL"} {
+ $handle add_rpmmd $f "FL" [ expr $solv::Repo_REPO_USE_LOADING | $solv::Repo_REPO_EXTEND_SOLVABLES | $solv::Repo_REPO_LOCALPOOL]
+ }
+ $f close
+ repo_writecachedrepo self $ext $repodata
+ return 1
+}
+
+### susetags
+
+proc repo_susetags_add_ext {selfName repodata what ext} {
+ upvar $selfName self
+ set where [repo_susetags_find self $what]
+ if {$where eq {}} {
+ return
+ }
+ set h [$repodata new_handle]
+ $repodata set_str $h $solv::SUSETAGS_FILE_NAME [lindex $where 0]
+ $repodata set_checksum $h $solv::SUSETAGS_FILE_CHECKSUM [lindex $where 1]
+ repo_generic_add_ext_keys self $ext $repodata $h
+ $repodata add_flexarray $solv::SOLVID_META $solv::REPOSITORY_EXTERNAL $h
+}
+
+proc repo_susetags_add_exts {selfName} {
+ upvar $selfName self
+ set repodata [$self(handle) add_repodata 0]
+ repo_susetags_add_ext self $repodata "packages.FL" "FL"
+ repo_susetags_add_ext self $repodata "packages.FL.gz" "FL"
+ $repodata internalize
+}
+
+proc repo_susetags_find {selfName what} {
+ upvar $selfName self
+ set di [$self(handle) Dataiterator_meta $solv::SUSETAGS_FILE_NAME $what $solv::Dataiterator_SEARCH_STRING]
+ $di prepend_keyname $solv::SUSETAGS_FILE
+ solv::iter d $di {
+ set dp [$d parentpos]
+ set checksum [$dp lookup_checksum $solv::SUSETAGS_FILE_CHECKSUM]
+ return [list $what $checksum]
+ }
+ return {}
+}
+
+proc repo_susetags_load {selfName pool} {
+ upvar $selfName self
+ if [repo_generic_load self $pool] {
+ return 1
+ }
+ puts -nonewline "susetags repo '$self(name)': "
+ set f [repo_download self {content} 0 {}]
+ if {$f eq {NULL}} {
+ puts "no content file, skipped"
+ repo_free_handle self
+ return 0
+ }
+ set self(cookie) [repo_calc_cookie_fp self $f]
+ if [repo_usecachedrepo self "-" 1] {
+ puts "cached"
+ return 1
+ }
+ set handle $self(handle)
+ $handle add_content $f
+ puts "fetching"
+ set defvendorid [[$handle cget -meta] lookup_id $solv::SUSETAGS_DEFAULTVENDOR]
+ set descrdir [[$handle cget -meta] lookup_str $solv::SUSETAGS_DESCRDIR]
+ if {$descrdir eq {NULL}} {
+ set descrdir "suse/setup/descr"
+ }
+ set packages [repo_susetags_find self "packages.gz"]
+ if {$packages eq {}} {
+ set packages [repo_susetags_find self "packages"]
+ }
+ if {$packages ne {}} {
+ set f [repo_download self "$descrdir/[lindex $packages 0]" 1 [lindex $packages 1] 1]
+ if {$f ne {NULL}} {
+ $handle add_susetags $f $defvendorid {} [expr $solv::Repo_REPO_NO_INTERNALIZE | $solv::Repo_SUSETAGS_RECORD_SHARES]
+ $f close
+ set packages [repo_susetags_find self "packages.en.gz"]
+ if {$packages eq {}} {
+ set packages [repo_susetags_find self "packages.en"]
+ }
+ if {$packages ne {}} {
+ set f [repo_download self "$descrdir/[lindex $packages 0]" 1 [lindex $packages 1] 1]
+ if {$f ne {NULL}} {
+ $handle add_susetags $f $defvendorid {} [expr $solv::Repo_REPO_NO_INTERNALIZE | $solv::Repo_REPO_REUSE_REPODATA | $solv::Repo_REPO_EXTEND_SOLVABLES ]
+ $f close
+ }
+ }
+ $handle internalize
+ }
+ }
+ repo_susetags_add_exts self
+ repo_writecachedrepo self
+ $self(handle) create_stubs
+ return 1
+}
+
+proc repo_susetags_packagespath {selfName} {
+ upvar $selfName self
+ set datadir [[$self(handle) cget -meta] lookup_str $solv::SUSETAGS_DATADIR]
+ return [expr {$datadir ne {} ? "$datadir/" : "suse/"}]
+}
+
+proc repo_susetags_load_ext {selfName repodata} {
+ upvar $selfName self
+ set filename [$repodata lookup_str $solv::SOLVID_META $solv::SUSETAGS_FILE_NAME]
+ set ext [string range $filename 9 10]
+ puts -nonewline "\[$self(name):$ext: "
+ flush stdout
+ if [repo_usecachedrepo self $ext] {
+ puts "cached]"
+ return 1
+ }
+ puts "fetching]"
+ set handle $self(handle)
+ set defvendorid [[$handle cget -meta] lookup_id $solv::SUSETAGS_DEFAULTVENDOR]
+ set descrdir [[$handle cget -meta] lookup_str $solv::SUSETAGS_DESCRDIR]
+ if {$descrdir eq {NULL}} {
+ set descrdir "suse/setup/descr"
+ }
+ set filechecksum [$repodata lookup_checksum $solv::SOLVID_META $solv::SUSETAGS_FILE_CHECKSUM]
+ set f [repo_download self "$descrdir/$filename" 1 $filechecksum]
+ if {$f eq {NULL}} {
+ return 0
+ }
+ set flags [expr $solv::Repo_REPO_USE_LOADING | $solv::Repo_REPO_EXTEND_SOLVABLES]
+ if {$ext ne "DL"} {
+ set flags [expr $flags | $solv::Repo_REPO_LOCALPOOL]
+ }
+ $handle add_susetags $f $defvendorid $ext $flags
+ $f close
+ repo_writecachedrepo self $ext $repodata
+ return 1
+}
+
+### unknown
+
+proc repo_unknown_load {selfName pool} {
+ upvar $selfName self
+ puts "unsupported repo '$self(name)': skipped"
+ return 0
+}
+
+### poor man's OO
+
+proc repo_load {selfName pool} {
+ upvar $selfName self
+ "repo_$self(type)_load" self $pool
+}
+
+proc repo_packagespath {selfName} {
+ upvar $selfName self
+ "repo_$self(type)_packagespath" self
+}
+
+proc repo_load_ext {selfName repodata} {
+ upvar $selfName self
+ "repo_$self(type)_load_ext" self $repodata
+}
+
+###
+
+proc load_stub {repodata} {
+ set code [catch {
+ upvar #0 [[$repodata cget -repo] cget -appdata] repo
+ if [info exists repo(handle)] {
+ return [repo_load_ext repo $repodata]
+ }
+ return 0
+ } res]
+ if {$code == 2} {
+ return $res
+ }
+ puts stderr $res
+ return 0
+}
+
+###
+
+set repoNames {}
+foreach reponame [lsort [glob -nocomplain -directory $reposdir *.repo]] {
+ set ini [::ini::open $reponame r]
+ foreach alias [::ini::sections $ini] {
+ upvar #0 [globalarray] repo
+ array set repo {enabled 0 priority 99 autorefresh 1 type rpm-md metadata_expire 900}
+ array set repo [::ini::get $ini $alias]
+ set repo(name) $alias
+ switch -exact -- $repo(type) {
+ rpm-md { set repo(type) repomd }
+ yast2 { set repo(type) susetags }
+ default { set repo(type) unknown }
+ }
+ lappend repoNames $repo(varName)
+ }
+ ::ini::close $ini
+}
+
+set pool [solv::new_Pool]
+$pool setarch
+$pool set_loadcallback load_stub
+
+upvar #0 [globalarray] sysrepo
+array set sysrepo [list name {@System} type system]
+repo_load sysrepo $pool
+
+foreach repoName $repoNames {
+ upvar 0 $repoName repo
+ if {$repo(enabled)} {
+ repo_load repo $pool
+ }
+}
+
+
+set cmd [lindex $::argv 0]
+set ::argv [lreplace $::argv 0 0]
+
+array set cmdabbrev [ list \
+ in install \
+ rm erase \
+ ls list \
+ ve verify \
+ se search \
+]
+if [info exists cmdabbrev($cmd)] {
+ set cmd $cmdabbrev($cmd)
+}
+
+if {$cmd eq "search"} {
+ set arg [lindex $::argv 0]
+ $pool createwhatprovides
+ set sel [$pool Selection]
+ set di [$pool Dataiterator $solv::SOLVABLE_NAME $arg [ expr $solv::Dataiterator_SEARCH_SUBSTRING | $solv::Dataiterator_SEARCH_NOCASE ]]
+ solv::iter d $di {
+ $sel add_raw $solv::Job_SOLVER_SOLVABLE [$d cget -solvid]
+ }
+ foreach s [$sel solvables] {
+ puts [format { - %s [%s]: %s} [$s str] [[$s cget -repo] cget -name] [$s lookup_str $solv::SOLVABLE_SUMMARY]]
+ }
+ exit
+}
+
+$pool addfileprovides
+$pool createwhatprovides
+
+array set cmdactionmap [ list \
+ install $solv::Job_SOLVER_INSTALL \
+ erase $solv::Job_SOLVER_ERASE \
+ up $solv::Job_SOLVER_UPDATE \
+ dup $solv::Job_SOLVER_DISTUPGRADE \
+ verify $solv::Job_SOLVER_VERIFY \
+ list 0 \
+ info 0 \
+]
+
+set jobs {}
+foreach arg $::argv {
+ set flags [expr $solv::Selection_SELECTION_NAME | $solv::Selection_SELECTION_PROVIDES | $solv::Selection_SELECTION_GLOB | \
+ $solv::Selection_SELECTION_CANON | $solv::Selection_SELECTION_DOTARCH | $solv::Selection_SELECTION_REL ]
+ switch -glob -- $arg {
+ "/*" {
+ set flags [expr $flags | $solv::Selection_SELECTION_FILELIST ]
+ if {$cmd eq "erase"} {
+ set flags [expr $flags | $solv::Selection_SELECTION_INSTALLED_ONLY ]
+ }
+ }
+ }
+ set sel [$pool select $arg $flags]
+ if [$sel isempty] {
+ set sel [$pool select $arg [expr $flags | $solv::Selection_SELECTION_NOCASE]]
+ if {![$sel isempty]} {
+ puts "\[ignoring case for '$arg']"
+ }
+ }
+ if [$sel isempty] {
+ puts "nothing matches '$arg'"
+ exit 1
+ }
+ if {[$sel flags] & $solv::Selection_SELECTION_FILELIST} {
+ puts "\[using file list match for '$arg']"
+ }
+ if {[$sel flags] & $solv::Selection_SELECTION_PROVIDES} {
+ puts "\[using capability match for '$arg']"
+ }
+ lappend jobs {*}[$sel jobs $cmdactionmap($cmd)]
+}
+
+if {$jobs eq {} && ($cmd eq "up" || $cmd eq "dup" || $cmd eq "verify") } {
+ set sel [$pool Selection_all]
+ lappend jobs {*}[$sel jobs $cmdactionmap($cmd)]
+}
+
+if {$jobs eq {}} {
+ puts "no package matched."
+ exit 1
+}
+
+if {$cmd eq "list" || $cmd eq "info"} {
+ foreach job $jobs {
+ foreach s [$job solvables] {
+ if {$cmd eq "info"} {
+ puts [format {Name: %s} [$s str]]
+ puts [format {Repo: %s} [[$s cget -repo] cget -name]]
+ puts [format {Summary: %s} [$s lookup_str $solv::SOLVABLE_SUMMARY]]
+ set str [$s lookup_str $solv::SOLVABLE_URL]
+ if {$str ne {}} {
+ puts [format {Url: %s} $str]
+ }
+ set str [$s lookup_str $solv::SOLVABLE_LICENSE]
+ if {$str ne {}} {
+ puts [format {License %s} $str]
+ }
+ puts [format {Description: %s} [$s lookup_str $solv::SOLVABLE_DESCRIPTION]]
+ puts {}
+ } else {
+ puts [format { - %s [%s]} [$s str] [[$s cget -repo] cget -name]]
+ puts [format { %s} [$s lookup_str $solv::SOLVABLE_SUMMARY]]
+ }
+ }
+ }
+ exit
+}
+
+#$pool set_debuglevel 1
+set solver [$pool Solver]
+$solver set_flag $solv::Solver_SOLVER_FLAG_SPLITPROVIDES 1
+if {$cmd eq "erase"} {
+ $solver set_flag $solv::Solver_SOLVER_FLAG_ALLOW_UNINSTALL 1
+}
+
+set problems [$solver solve $jobs]
+if {$problems ne {}} {
+ set pcnt 1
+ foreach problem $problems {
+ puts [format {Problem %d/%d:} $pcnt [llength $problems]]
+ puts [$problem str]
+ incr pcnt
+ }
+ exit 1
+}
+
+set trans [$solver transaction]
+
+if [$trans isempty] {
+ puts "Nothing to do."
+ exit
+}
+
+puts {}
+puts "Transaction summary:"
+puts {}
+foreach cl [$trans classify [expr $solv::Transaction_SOLVER_TRANSACTION_SHOW_OBSOLETES | $solv::Transaction_SOLVER_TRANSACTION_OBSOLETE_IS_UPGRADE]] {
+ switch -- [$cl cget -type] \
+ $solv::Transaction_SOLVER_TRANSACTION_ERASE {
+ puts [format {%d erased packages:} [$cl cget -count]]
+ } \
+ $solv::Transaction_SOLVER_TRANSACTION_INSTALL {
+ puts [format {%d installed packages:} [$cl cget -count]]
+ } \
+ $solv::Transaction_SOLVER_TRANSACTION_REINSTALLED {
+ puts [format {%d reinstalled packages:} [$cl cget -count]]
+ } \
+ $solv::Transaction_SOLVER_TRANSACTION_DOWNGRADED {
+ puts [format {%d downgraded packages:} [$cl cget -count]]
+ } \
+ $solv::Transaction_SOLVER_TRANSACTION_CHANGED {
+ puts [format {%d changed packages:} [$cl cget -count]]
+ } \
+ $solv::Transaction_SOLVER_TRANSACTION_UPGRADED {
+ puts [format {%d upgraded packages:} [$cl cget -count]]
+ } \
+ $solv::Transaction_SOLVER_TRANSACTION_VENDORCHANGE {
+ puts [format {%d vendor changes from '%s' to '%s':} [$cl cget -count] [$cl cget -fromstr] [$cl cget -tostr]]
+ } \
+ $solv::Transaction_SOLVER_TRANSACTION_ARCHCHANGE {
+ puts [format {%d archchanges from '%s' to '%s':} [$cl cget -count] [$cl cget -fromstr] [$cl cget -tostr]]
+ } \
+ default continue
+ foreach p [$cl solvables] {
+ set cltype [$cl cget -type]
+ if {$cltype == $solv::Transaction_SOLVER_TRANSACTION_UPGRADED || $cltype ==$solv::Transaction_SOLVER_TRANSACTION_DOWNGRADED} {
+ set op [$trans othersolvable $p]
+ puts [format { - %s -> %s} [$p str] [$p str]]
+ } else {
+ puts [format { - %s} [$p str]]
+ }
+ }
+ puts {}
+}
+puts [format {install size change: %d K} [$trans calc_installsizechange]]
+puts {}
+
+while 1 {
+ puts -nonewline "OK to continue (y/n)? "
+ flush stdout
+ set yn [gets stdin]
+ if {$yn eq "y"} {
+ break
+ }
+ if {$yn eq "n" || $yn eq "q"} {
+ exit
+ }
+}
+
+set newpkgs [$trans newsolvables]
+array set newpkgs_f {}
+if {$newpkgs ne {}} {
+ set downloadsize 0
+ foreach p $newpkgs {
+ set downloadsize [expr $downloadsize + [$p lookup_num $solv::SOLVABLE_DOWNLOADSIZE]]
+ }
+ puts [format {Downloading %d packages, %d K} [llength $newpkgs] [expr $downloadsize / 1024]]
+ foreach p $newpkgs {
+ upvar #0 [[$p cget -repo] cget -appdata] repo
+ set location [$p lookup_location]
+ if {$location eq {}} {
+ continue
+ }
+ set location "[repo_packagespath repo][lindex $location 0]"
+ set checksum [$p lookup_checksum $solv::SOLVABLE_CHECKSUM]
+ set f [repo_download repo $location 0 $checksum]
+ set newpkgs_f([$p cget -id]) $f
+ puts -nonewline "."
+ flush stdout
+ }
+ puts {}
+}
+
+puts "Committing transaction:"
+$trans order
+foreach p [$trans steps] {
+ set steptype [$trans steptype $p $solv::Transaction_SOLVER_TRANSACTION_RPM_ONLY]
+ if {$steptype == $solv::Transaction_SOLVER_TRANSACTION_ERASE} {
+ puts "erase [$p str]"
+ regsub {^[0-9]+:} [$p cget -evr] {} nvr
+ set nvr "[$p cget -name]-$nvr.[$p cget -arch]"
+ exec -ignorestderr -- rpm -e --nodeps --nodigest --nosignature $nvr
+ } elseif {$steptype == $solv::Transaction_SOLVER_TRANSACTION_INSTALL || $steptype == $solv::Transaction_SOLVER_TRANSACTION_MULTIINSTALL} {
+ puts "install [$p str]"
+ set f $newpkgs_f([$p cget -id])
+ set mode [expr {$steptype == $solv::Transaction_SOLVER_TRANSACTION_INSTALL ? "-U" : "-i"}]
+ $f cloexec 0
+ exec -ignorestderr -- rpm $mode --force --nodeps --nodigest --nosignature "/dev/fd/[$f fileno]"
+ }
+}
SET_TARGET_PROPERTIES(libsolvext PROPERTIES OUTPUT_NAME "solvext")
SET_TARGET_PROPERTIES(libsolvext PROPERTIES SOVERSION ${LIBSOLVEXT_SOVERSION})
+SET_TARGET_PROPERTIES(libsolvext PROPERTIES INSTALL_NAME_DIR ${LIB_INSTALL_DIR})
INSTALL (FILES ${libsolvext_HEADERS} DESTINATION "${INCLUDE_INSTALL_DIR}/solv")
INSTALL (TARGETS libsolvext LIBRARY DESTINATION ${LIB_INSTALL_DIR} ARCHIVE DESTINATION ${LIB_INSTALL_DIR})
#include "pool.h"
#include "pool_parserpmrichdep.h"
-#define REL_THEN 0
-#define REL_ELSE 0
-
static struct RichOpComp {
const char *n;
int l;
Id fl;
} RichOps[] = {
- { "&&", 2, REL_AND },
- { "&", 1, REL_AND },
- { "AND", 3, REL_AND },
- { "||", 2, REL_OR },
- { "|", 1, REL_OR },
- { "OR", 2, REL_OR },
- { "IF", 2, REL_COND },
- { "THEN", 4, REL_THEN },
- { "?", 1, REL_THEN },
- { "ELSE", 4, REL_ELSE },
- { ":", 1, REL_ELSE },
+ { "and", 3, REL_AND },
+ { "or", 2, REL_OR },
+ { "if", 2, REL_COND },
+ { "else", 4, REL_ELSE },
{ NULL, 0, 0},
};
fl = op->fl;
if (!fl)
return 0;
- if (chainfl == REL_THEN && fl == REL_ELSE)
+ if (chainfl == REL_COND && fl == REL_ELSE)
chainfl = 0;
if (chainfl && fl != chainfl)
return 0;
return 0;
}
l = fread(buf, 1, sizeof(buf), fp);
- if (l < 8 + 60 || strncmp((char *)buf, "!<arch>\ndebian-binary ", 8 + 16) != 0)
+ if (l < 8 + 60 || (strncmp((char *)buf, "!<arch>\ndebian-binary ", 8 + 16) != 0 && strncmp((char *)buf, "!<arch>\ndebian-binary/ ", 8 + 16) != 0))
{
pool_error(pool, -1, "%s: not a deb package", deb);
fclose(fp);
fclose(fp);
return 0;
}
- if (strncmp((char *)buf + 8 + 60 + vlen, "control.tar.gz ", 16) != 0)
+ if (strncmp((char *)buf + 8 + 60 + vlen, "control.tar.gz ", 16) != 0 && strncmp((char *)buf + 8 + 60 + vlen, "control.tar.gz/ ", 16) != 0)
{
pool_error(pool, -1, "%s: control.tar.gz is not second entry", deb);
fclose(fp);
char *arch;
char *version;
char *filename;
+ char *disttag = 0;
+ char *distepoch = 0;
if ((epochstr = strchr(nvra, '@')) != 0)
{
char *sizestr;
*sizestr++ = 0;
if ((groupstr = strchr(sizestr, '@')) != 0)
{
- char *n;
*groupstr++ = 0;
- if ((n = strchr(groupstr, '@')) != 0)
- *n = 0;
+ if ((disttag = strchr(groupstr, '@')) != 0)
+ {
+ *disttag++ = 0;
+ if ((distepoch = strchr(disttag, '@')) != 0)
+ {
+ char *n;
+ *distepoch++ = 0;
+ if ((n = strchr(distepoch, '@')) != 0)
+ *n = 0;
+ }
+ }
if (*groupstr)
repodata_set_poolstr(data, s - pool->solvables, SOLVABLE_GROUP, groupstr);
}
- repodata_set_num(data, s - pool->solvables, SOLVABLE_INSTALLSIZE, strtoull(sizestr, 0, 10));
+ if (*sizestr)
+ repodata_set_num(data, s - pool->solvables, SOLVABLE_INSTALLSIZE, strtoull(sizestr, 0, 10));
}
}
filename = pool_tmpjoin(pool, nvra, ".rpm", 0);
*arch++ = 0;
s->arch = pool_str2id(pool, arch, 1);
}
- /* argh, do we have a distepoch or not, check self-provides */
- if (s->provides)
+ if (disttag && *disttag)
{
- Id id, lastid, *idp = s->repo->idarraydata + s->provides;
- lastid = 0;
- for (idp = s->repo->idarraydata + s->provides; (id = *idp) != 0; idp++)
- {
- const char *evr, *name;
- int namel;
- Reldep *rd;
- if (!ISRELDEP(id))
- continue;
- rd = GETRELDEP(pool, id);
- if (rd->flags != REL_EQ)
- continue;
- name = pool_id2str(pool, rd->name);
- namel = strlen(name);
- if (strncmp(name, nvra, namel) != 0 || nvra[namel] != '-')
- continue;
- evr = pool_id2str(pool, rd->evr);
- evr = strrchr(evr, '-');
- if (evr && strchr(evr, ':') != 0)
- lastid = id;
- }
- if (lastid)
- {
- /* self provides found, and it contains a distepoch */
- /* replace with self-provides distepoch to get rid of the disttag */
- char *nvradistepoch = strrchr(nvra, '-');
- if (nvradistepoch)
- {
- Reldep *rd = GETRELDEP(pool, lastid);
- const char *evr = pool_id2str(pool, rd->evr);
- evr = strrchr(evr, '-');
- if (evr && (evr = strchr(evr, ':')) != 0)
- {
- if (strlen(evr) < strlen(nvradistepoch))
- strcpy(nvradistepoch, evr);
- }
- }
- }
+ /* strip disttag from release */
+ char *n = strrchr(nvra, '-');
+ if (n && !strncmp(n + 1, disttag, strlen(disttag)))
+ *n = 0;
+ }
+ if (distepoch && *distepoch)
+ {
+ /* add distepoch */
+ int le = strlen(distepoch);
+ int ln = strlen(nvra);
+ nvra[ln++] = ':';
+ memmove(nvra + ln, distepoch, le); /* may overlap */
+ nvra[le + ln] = 0;
}
version = strrchr(nvra, '-');
if (version)
#define DEP_STRONG (1 << 27)
#define DEP_PRE_IN ((1 << 6) | (1 << 9) | (1 << 10))
#define DEP_PRE_UN ((1 << 6) | (1 << 11) | (1 << 12))
-#define DEP_RICH (1 << 29)
#define FILEFLAG_GHOST (1 << 6)
if (!strncmp(n[i], "rpmlib(", 7))
continue;
#ifdef ENABLE_COMPLEX_DEPS
- if ((f[i] & (DEP_RICH|DEP_LESS| DEP_EQUAL|DEP_GREATER)) == DEP_RICH && n[i][0] == '(')
+ if ((f[i] & (DEP_LESS|DEP_EQUAL|DEP_GREATER)) == 0 && n[i][0] == '(')
{
id = pool_parserpmrichdep(pool, n[i]);
if (id)
{ REL_COND, "<IF>" },
{ REL_COMPAT, "compat >=" },
{ REL_KIND, "<KIND>" },
+ { REL_ELSE, "<ELSE>" },
{ REL_LT, "<" },
{ 0, 0 }
};
int
-testcase_write(Solver *solv, char *dir, int resultflags, const char *testcasename, const char *resultname)
+testcase_write(Solver *solv, const char *dir, int resultflags, const char *testcasename, const char *resultname)
{
Pool *pool = solv->pool;
Repo *repo;
}
Solver *
-testcase_read(Pool *pool, FILE *fp, char *testcase, Queue *job, char **resultp, int *resultflagsp)
+testcase_read(Pool *pool, FILE *fp, const char *testcase, Queue *job, char **resultp, int *resultflagsp)
{
Solver *solv;
char *buf, *bufp;
}
char *
-testcase_resultdiff(char *result1, char *result2)
+testcase_resultdiff(const char *result1, const char *result2)
{
Strqueue sq1, sq2, osq;
char *r;
extern int testcase_setsolverflags(Solver *solv, const char *str);
extern void testcase_resetsolverflags(Solver *solv);
extern char *testcase_solverresult(Solver *solv, int flags);
-extern int testcase_write(Solver *solv, char *dir, int resultflags, const char *testcasename, const char *resultname);
-extern Solver *testcase_read(Pool *pool, FILE *fp, char *testcase, Queue *job, char **resultp, int *resultflagsp);
-extern char *testcase_resultdiff(char *result1, char *result2);
+extern int testcase_write(Solver *solv, const char *dir, int resultflags, const char *testcasename, const char *resultname);
+extern Solver *testcase_read(Pool *pool, FILE *fp, const char *testcase, Queue *job, char **resultp, int *resultflagsp);
+extern char *testcase_resultdiff(const char *result1, const char *result2);
--- /dev/null
+libdir=@LIB_INSTALL_DIR@
+includedir=@INCLUDE_INSTALL_DIR@
+
+Name: libsolv
+Description: Library for solving packages and reading repositories
+Version: @VERSION@
+Libs: -L${libdir} -lsolvext -lsolv
+Cflags: -I${includedir}
-------------------------------------------------------------------
+Tue Sep 1 13:37:11 CEST 2015 - mls@suse.de
+
+- added tcl bindings
+- improve debian ar archive handling
+- bindings: set the CLOEXEC flags in xfopen
+- bindings: support testcase writing
+- support REL_ELSE as evr of REL_COND
+- bump version to 0.6.12
+
+-------------------------------------------------------------------
Tue Jun 2 11:41:10 CEST 2015 - mls@suse.de
- add forgotten sha-512 support to data_skip
BuildRequires: libneon0.26-devel
%endif
%if 0%{?fedora_version} || 0%{?rhel_version} >= 600 || 0%{?centos_version} >= 600
-BuildRequires: db4-devel
+BuildRequires: db-devel
%endif
%if 0%{?suse_version}
%if 0%{?suse_version} < 1030
CMAKE_FLAGS="-DFEDORA=1"
%endif
%if 0%{?suse_version}
-CMAKE_FLAGS="-DSUSE=1 -DENABLE_APPDATA=1"
+CMAKE_FLAGS="-DSUSE=1 -DENABLE_APPDATA=1 -DENABLE_COMPS=1"
%endif
cmake $CMAKE_FLAGS \
%{_mandir}/man1/helix2solv*
%endif
%{_datadir}/cmake/Modules/*
+%{_libdir}/pkgconfig/libsolv.pc
%{_mandir}/man3/*
%files demo
SET_TARGET_PROPERTIES(libsolv PROPERTIES OUTPUT_NAME "solv")
SET_TARGET_PROPERTIES(libsolv PROPERTIES SOVERSION ${LIBSOLV_SOVERSION})
+SET_TARGET_PROPERTIES(libsolv PROPERTIES INSTALL_NAME_DIR ${LIB_INSTALL_DIR})
INSTALL (FILES ${libsolv_HEADERS} DESTINATION "${INCLUDE_INSTALL_DIR}/solv")
INSTALL (TARGETS libsolv LIBRARY DESTINATION ${LIB_INSTALL_DIR} ARCHIVE DESTINATION ${LIB_INSTALL_DIR})
return 0;
}
+int
+solv_chksum_cmp(Chksum *chk, Chksum *chk2)
+{
+ int len;
+ const unsigned char *res1, *res2;
+ if (chk == chk2)
+ return 1;
+ if (!chk || !chk2 || chk->type != chk2->type)
+ return 0;
+ res1 = solv_chksum_get(chk, &len);
+ res2 = solv_chksum_get(chk2, 0);
+ return memcmp(res1, res2, len) == 0 ? 1 : 0;
+}
const char *solv_chksum_type2str(Id type);
Id solv_chksum_str2type(const char *str);
int solv_chksum_len(Id type);
+int solv_chksum_cmp(Chksum *chk, Chksum *chk2);
#ifdef LIBSOLV_INTERNAL
#endif
/* invert all literals in the blocks. note that this also turns DNF into CNF and vice versa */
-static void
-invert_depblocks(Pool *pool, Queue *bq, int start)
+static int
+invert_depblocks(Pool *pool, Queue *bq, int start, int r)
{
int i, j, end;
+ if (r == 0 || r == 1)
+ return r ? 0 : 1;
expand_simpledeps(pool, bq, start, 0);
end = bq->count;
for (i = j = start; i < end; i++)
}
j = i + 1;
}
+ return -1;
}
/*
if (rd->flags == REL_AND || rd->flags == REL_OR || rd->flags == REL_COND)
{
int rdflags = rd->flags;
+ Id name = rd->name;
+ Id evr = rd->evr;
int r, mode;
- /* in inverted mode, COND means AND. otherwise it means OR NOT */
- if (rdflags == REL_COND && todnf)
- rdflags = REL_AND;
- mode = rdflags == REL_AND ? 0 : 1;
+ if (rdflags == REL_COND)
+ {
+ /* check for relly complex ELSE case */
+ if (ISRELDEP(evr))
+ {
+ Reldep *rd2 = GETRELDEP(pool, evr);
+ if (rd2->flags == REL_ELSE)
+ {
+ int r2;
+ /* really complex case */
+ if ((flags & CPLXDEPS_ELSE_MASK) == CPLXDEPS_ELSE_AND_1)
+ {
+ /* A OR ~B */
+ rdflags = REL_COND;
+ evr = rd2->name;
+ }
+ else if ((flags & CPLXDEPS_ELSE_MASK) == CPLXDEPS_ELSE_AND_2)
+ {
+ /* C OR B */
+ rdflags = REL_OR;
+ name = rd2->evr;
+ evr = rd2->name;
+ }
+ else if ((flags & CPLXDEPS_ELSE_MASK) == CPLXDEPS_ELSE_OR_1)
+ {
+ /* A AND B */
+ rdflags = REL_AND;
+ evr = rd2->name;
+ }
+ else if ((flags & CPLXDEPS_ELSE_MASK) == CPLXDEPS_ELSE_OR_2)
+ {
+ /* A AND C */
+ rdflags = REL_AND;
+ evr = rd2->evr;
+ }
+ else if ((flags & CPLXDEPS_ELSE_MASK) == CPLXDEPS_ELSE_OR_3)
+ {
+ /* C AND ~B */
+ rdflags = REL_ELSE;
+ name = rd2->evr;
+ evr = rd2->name;
+ }
+ else if (!todnf)
+ {
+ /* we want AND: A IF (B ELSE C) -> (A OR ~B) AND (C OR B) */
+ r = normalize_dep(pool, dep, bq, flags | CPLXDEPS_ELSE_AND_1);
+ if (r == 0 && (flags & CPLXDEPS_DONTFIX) == 0)
+ return 0;
+ r2 = normalize_dep(pool, dep, bq, flags | CPLXDEPS_ELSE_AND_2);
+ if (r2 == 0 && (flags & CPLXDEPS_DONTFIX) == 0)
+ {
+ queue_truncate(bq, bqcnt);
+ return 0;
+ }
+ if (r == -1 || r2 == -1)
+ return -1;
+ return r == 1 || r2 == 1 ? 1 : 0;
+ }
+ else
+ {
+ int r2, r3;
+ /* we want OR: A IF (B ELSE C) -> (A AND B) OR (A AND C) OR (~B AND C) */
+ r = normalize_dep(pool, dep, bq, flags | CPLXDEPS_ELSE_OR_1);
+ if (r == 1)
+ return 1;
+ r2 = normalize_dep(pool, dep, bq, flags | CPLXDEPS_ELSE_OR_2);
+ if (r2 == 1)
+ {
+ queue_truncate(bq, bqcnt);
+ return 1;
+ }
+ r3 = normalize_dep(pool, dep, bq, flags | CPLXDEPS_ELSE_OR_3);
+ if (r3 == 1)
+ {
+ queue_truncate(bq, bqcnt);
+ return 1;
+ }
+ if (r == -1 || r2 == -1 || r3 == -1)
+ return -1;
+ return 0;
+ }
+ }
+ }
+ }
+ mode = rdflags == REL_AND || rdflags == REL_ELSE ? 0 : 1;
/* get blocks of first argument */
- r = normalize_dep(pool, rd->name, bq, flags);
+ r = normalize_dep(pool, name, bq, flags);
if (r == 0)
{
+ if (rdflags == REL_ELSE)
+ return 0;
if (rdflags == REL_AND && (flags & CPLXDEPS_DONTFIX) == 0)
return 0;
if (rdflags == REL_COND)
{
- r = normalize_dep(pool, rd->evr, bq, (flags ^ CPLXDEPS_TODNF) & ~CPLXDEPS_DONTFIX);
- if (r == 0 || r == 1)
- return r == 0 ? 1 : 0;
- invert_depblocks(pool, bq, bqcnt); /* invert block for COND */
- return r;
+ r = normalize_dep(pool, evr, bq, (flags ^ CPLXDEPS_TODNF) & ~CPLXDEPS_DONTFIX);
+ return invert_depblocks(pool, bq, bqcnt, r); /* invert block for COND */
}
- return normalize_dep(pool, rd->evr, bq, flags);
+ return normalize_dep(pool, evr, bq, flags);
}
if (r == 1)
{
- if (rdflags != REL_AND)
+ if (rdflags == REL_ELSE)
+ {
+ r = normalize_dep(pool, evr, bq, (flags ^ CPLXDEPS_TODNF) & ~CPLXDEPS_DONTFIX);
+ return invert_depblocks(pool, bq, bqcnt, r); /* invert block for ELSE */
+ }
+ if (rdflags == REL_OR || rdflags == REL_COND)
return 1;
- return normalize_dep(pool, rd->evr, bq, flags);
+ return normalize_dep(pool, evr, bq, flags);
}
/* get blocks of second argument */
bqcnt2 = bq->count;
/* COND is OR with NEG on evr block, so we invert the todnf flag in that case */
- r = normalize_dep(pool, rd->evr, bq, rdflags == REL_COND ? ((flags ^ CPLXDEPS_TODNF) & ~CPLXDEPS_DONTFIX) : flags);
+ r = normalize_dep(pool, evr, bq, rdflags == REL_COND || rdflags == REL_ELSE ? ((flags ^ CPLXDEPS_TODNF) & ~CPLXDEPS_DONTFIX) : flags);
+ if (rdflags == REL_COND || rdflags == REL_ELSE)
+ r = invert_depblocks(pool, bq, bqcnt2, r); /* invert 2nd block */
if (r == 0)
{
if (rdflags == REL_OR)
if (rdflags == REL_AND && (flags & CPLXDEPS_DONTFIX) != 0)
return -1;
queue_truncate(bq, bqcnt);
- return rdflags == REL_COND ? 1 : 0;
+ return 0;
}
if (r == 1)
{
- if (rdflags == REL_OR)
+ if (rdflags == REL_COND || rdflags == REL_OR)
{
queue_truncate(bq, bqcnt);
return 1;
}
return -1;
}
- if (rdflags == REL_COND)
- invert_depblocks(pool, bq, bqcnt2); /* invert 2nd block */
if (mode == todnf)
{
/* simple case: just join em. nothing more to do here. */
expand_simpledeps(pool, bq, bqcnt, 0);
}
if ((flags & CPLXDEPS_INVERT) != 0)
- {
- if (i == 0 || i == 1)
- i ^= 1;
- else
- invert_depblocks(pool, bq, bqcnt);
- }
+ i = invert_depblocks(pool, bq, bqcnt, i);
#ifdef CPLXDEBUG
if (i == 0)
printf("NONE\n");
return i;
}
+void
+pool_add_pos_literals_complex_dep(Pool *pool, Id dep, Queue *q, Map *m, int neg)
+{
+ while (ISRELDEP(dep))
+ {
+ Reldep *rd = GETRELDEP(pool, dep);
+ if (rd->flags != REL_AND && rd->flags != REL_OR && rd->flags != REL_COND)
+ break;
+ pool_add_pos_literals_complex_dep(pool, rd->name, q, m, neg);
+ dep = rd->evr;
+ if (rd->flags == REL_COND)
+ {
+ neg = !neg;
+ if (ISRELDEP(dep))
+ {
+ Reldep *rd2 = GETRELDEP(pool, rd->evr);
+ if (rd2->flags == REL_ELSE)
+ {
+ pool_add_pos_literals_complex_dep(pool, rd2->evr, q, m, !neg);
+ dep = rd2->name;
+ }
+ }
+ }
+ }
+ if (!neg)
+ {
+ Id p, pp;
+ FOR_PROVIDES(p, pp, dep)
+ if (!MAPTST(m, p))
+ queue_push(q, p);
+ }
+}
+
#endif /* ENABLE_COMPLEX_DEPS */
}
extern int pool_normalize_complex_dep(Pool *pool, Id dep, Queue *bq, int flags);
+extern void pool_add_pos_literals_complex_dep(Pool *pool, Id dep, Queue *q, Map *m, int neg);
#define CPLXDEPS_TODNF (1 << 0)
#define CPLXDEPS_EXPAND (1 << 1)
#define CPLXDEPS_NAME (1 << 3)
#define CPLXDEPS_DONTFIX (1 << 4)
+#define CPLXDEPS_ELSE_AND_1 (1 << 8)
+#define CPLXDEPS_ELSE_AND_2 (1 << 9)
+#define CPLXDEPS_ELSE_OR_1 (1 << 10)
+#define CPLXDEPS_ELSE_OR_2 (1 << 11)
+#define CPLXDEPS_ELSE_OR_3 (1 << 12)
+#define CPLXDEPS_ELSE_MASK (0x1f00)
+
#endif
solv_bin2hex;
solv_calloc;
solv_chksum_add;
+ solv_chksum_cmp;
solv_chksum_create;
solv_chksum_create_clone;
solv_chksum_create_from_bin;
*wp++ = id;
}
newoff = wp - pool->whatprovidesauxdata;
- solv_realloc(pool->whatprovidesauxdata, newoff * sizeof(Id));
+ pool->whatprovidesauxdata = solv_realloc(pool->whatprovidesauxdata, newoff * sizeof(Id));
POOL_DEBUG(SOLV_DEBUG_STATS, "shrunk whatprovidesauxdata from %d to %d\n", pool->whatprovidesauxdataoff, newoff);
pool->whatprovidesauxdataoff = newoff;
}
case REL_AND:
case REL_OR:
+ case REL_COND:
+ if (flags == REL_COND)
+ {
+ if (ISRELDEP(evr))
+ {
+ Reldep *rd2 = GETRELDEP(pool, evr);
+ evr = rd2->flags == REL_ELSE ? rd2->evr : 0;
+ }
+ else
+ evr = 0; /* assume cond is true */
+ }
wp = pool_whatprovides(pool, name);
if (!pool->whatprovidesdata[wp])
- wp = pool_whatprovides(pool, evr);
- else
+ wp = evr ? pool_whatprovides(pool, evr) : 1;
+ else if (evr)
{
/* sorted merge */
pp2 = pool_whatprovides_ptr(pool, evr);
}
break;
- case REL_COND:
- /* assume the condition is true */
- wp = pool_whatprovides(pool, name);
- break;
-
case REL_NAMESPACE:
if (name == NAMESPACE_OTHERPROVIDERS)
{
#define REL_COMPAT 23
#define REL_KIND 24 /* for filters only */
#define REL_MULTIARCH 25 /* debian multiarch annotation */
+#define REL_ELSE 26 /* only as evr part of REL_COND */
#if !defined(__GNUC__) && !defined(__attribute__)
# define __attribute__(x)
"sparcv9", "sparcv9:sparcv8:sparc",
"sparcv8", "sparcv8:sparc",
"sparc", "sparc",
+ "mips", "mips",
"mipsel", "mipsel",
+ "mips64", "mips64",
+ "mips64el", "mips64el",
"m68k", "m68k",
#ifdef FEDORA
"ia32e", "ia32e:x86_64:athlon:i686:i586:i486:i386",
return " compat >= ";
case REL_KIND:
return " KIND ";
+ case REL_ELSE:
+ return " ELSE ";
default:
break;
}
return;
}
di->repoid = 0;
- di->data = di->repo->repodata + di->pool->pos.repodataid;
- di->repodataid = 0;
- di->solvid = solvid;
- di->state = di_enterrepo;
- di->flags |= SEARCH_THISSOLVID;
- return;
+ if (!di->pool->pos.repodataid && di->pool->pos.solvid == SOLVID_META) {
+ solvid = SOLVID_META; /* META pos hack */
+ } else {
+ di->data = di->repo->repodata + di->pool->pos.repodataid;
+ di->repodataid = 0;
+ }
}
- if (solvid > 0)
+ else if (solvid > 0)
{
di->repo = di->pool->solvables[solvid].repo;
di->repoid = 0;
}
- else if (di->repoid > 0)
+ if (di->repoid > 0)
{
if (!di->pool->urepos)
{
di->repoid = 1;
di->repo = di->pool->repos[di->repoid];
}
- di->repodataid = 1;
+ if (solvid != SOLVID_POS)
+ di->repodataid = 1;
di->solvid = solvid;
if (solvid)
di->flags |= SEARCH_THISSOLVID;
Reldep *rd = GETRELDEP(pool, dep);
if (rd->flags >= 8)
{
- if (rd->flags == REL_AND || rd->flags == REL_COND)
+ if (rd->flags == REL_COND)
+ return 1;
+ if (rd->flags == REL_AND)
{
if (!dep_possible(solv, rd->name, m))
return 0;
}
/*-----------------------------------------
- * add recommends to the work queue
+ * add recommends/suggests to the work queue
*/
if (s->recommends && m)
{
recp = s->repo->idarraydata + s->recommends;
while ((rec = *recp++) != 0)
{
+#ifdef ENABLE_COMPLEX_DEPS
+ if (pool_is_complex_dep(pool, rec))
+ {
+ pool_add_pos_literals_complex_dep(pool, rec, &workq, m, 0);
+ continue;
+ }
+#endif
FOR_PROVIDES(p, pp, rec)
if (!MAPTST(m, p))
queue_push(&workq, p);
sugp = s->repo->idarraydata + s->suggests;
while ((sug = *sugp++) != 0)
{
+#ifdef ENABLE_COMPLEX_DEPS
+ if (pool_is_complex_dep(pool, sug))
+ {
+ pool_add_pos_literals_complex_dep(pool, sug, &workq, m, 0);
+ continue;
+ }
+#endif
FOR_PROVIDES(p, pp, sug)
if (!MAPTST(m, p))
queue_push(&workq, p);
if (ISRELDEP(dep))
{
Reldep *rd = GETRELDEP(pool, dep);
+ if (rd->flags == REL_COND)
+ {
+ int r1, r2;
+ if (ISRELDEP(rd->evr))
+ {
+ Reldep *rd2 = GETRELDEP(pool, rd->evr);
+ if (rd2->flags == REL_ELSE)
+ {
+ r1 = solver_dep_fulfilled_alreadyinstalled(solv, rd2->name);
+ if (r1)
+ {
+ r2 = solver_dep_fulfilled_alreadyinstalled(solv, rd->name);
+ return r2 && r1 == 2 ? 2 : r2;
+ }
+ return solver_dep_fulfilled_alreadyinstalled(solv, rd2->evr);
+ }
+ }
+ r1 = solver_dep_fulfilled_alreadyinstalled(solv, rd->name);
+ r2 = !solver_dep_fulfilled_alreadyinstalled(solv, rd->evr);
+ if (!r1 && !r2)
+ return 0;
+ return r1 == 2 ? 2 : 1;
+ }
if (rd->flags == REL_AND)
{
int r2, r1 = solver_dep_fulfilled_alreadyinstalled(solv, rd->name);
if (ISRELDEP(dep))
{
Reldep *rd = GETRELDEP(pool, dep);
- if (rd->flags == REL_AND || rd->flags == REL_COND)
+ if (rd->flags == REL_COND)
+ {
+ if (ISRELDEP(rd->evr))
+ {
+ Reldep *rd2 = GETRELDEP(pool, rd->evr);
+ if (rd2->flags == REL_ELSE)
+ {
+ if (solver_dep_fulfilled(solv, rd2->name))
+ return solver_dep_fulfilled(solv, rd->name);
+ return solver_dep_fulfilled(solv, rd2->evr);
+ }
+ }
+ if (solver_dep_fulfilled(solv, rd->name))
+ return 1;
+ return !solver_dep_fulfilled(solv, rd->evr);
+ }
+ if (rd->flags == REL_AND)
{
if (!solver_dep_fulfilled(solv, rd->name))
return 0;
int resultflags = 0;
int debuglevel = 0;
int writeresult = 0;
+ char *writetestcase = 0;
int multijob = 0;
int rescallback = 0;
int c;
const char *p;
queue_init(&solq);
- while ((c = getopt(argc, argv, "vmrhl:s:")) >= 0)
+ while ((c = getopt(argc, argv, "vmrhl:s:T:")) >= 0)
{
switch (c)
{
else
queue_push2(&solq, 1, atoi(optarg));
break;
+ case 'T':
+ writetestcase = optarg;
+ break;
default:
usage(1);
break;
else
{
int pcnt = solver_solve(solv, &job);
+ if (writetestcase)
+ testcase_write(solv, writetestcase, resultflags, 0, 0);
if (pcnt && solq.count)
{
int i, taken = 0;