You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1057 lines
30 KiB
1057 lines
30 KiB
#include <python2.6/Python.h>
|
|
|
|
#include "dpkg.h"
|
|
|
|
#define MAKE_PY_LIST(L,S,E,I,V) \
|
|
do { \
|
|
L = PyList_New(0); \
|
|
if (!L) break; \
|
|
for (S; E; I) { \
|
|
PyObject *EL; \
|
|
EL = Py_BuildValue V; \
|
|
if (!EL) { \
|
|
Py_DECREF(L); \
|
|
L = NULL; \
|
|
break; \
|
|
} \
|
|
PyList_Append(L, EL); \
|
|
Py_DECREF(EL); \
|
|
} \
|
|
if (L) PyList_Sort(L); \
|
|
} while(0)
|
|
|
|
/**************************************************************************
|
|
* britney.Packages -- dpkg_packages wrapper
|
|
*******************************************/
|
|
|
|
typedef enum { DONTFREE, FREE } dpkgpackages_freeme;
|
|
typedef struct {
|
|
PyObject_HEAD
|
|
dpkg_packages *pkgs;
|
|
PyObject *ref; /* object packages are "in" */
|
|
dpkgpackages_freeme freeme; /* free pkgs when deallocing? */
|
|
} dpkgpackages;
|
|
|
|
staticforward PyTypeObject Packages_Type;
|
|
|
|
static PyObject *dpkgpackages_new(dpkg_packages *pkgs,
|
|
dpkgpackages_freeme freeme, PyObject *ref)
|
|
{
|
|
dpkgpackages *res;
|
|
|
|
res = PyObject_NEW(dpkgpackages, &Packages_Type);
|
|
if (res == NULL) return NULL;
|
|
|
|
res->pkgs = pkgs;
|
|
res->ref = ref; Py_INCREF(res->ref);
|
|
res->freeme = freeme;
|
|
|
|
return (PyObject *) res;
|
|
}
|
|
|
|
static void dpkgpackages_dealloc(dpkgpackages *self) {
|
|
if (self->freeme == FREE) free_packages(self->pkgs);
|
|
Py_XDECREF(self->ref);
|
|
self->pkgs = NULL;
|
|
self->ref = NULL;
|
|
PyObject_DEL(self);
|
|
}
|
|
|
|
|
|
static dpkg_collected_package *dpkgpackages_lookuppkg(dpkgpackages *self,
|
|
char *pkgname)
|
|
{
|
|
dpkg_collected_package *cpkg = NULL;
|
|
cpkg = lookup_packagetbl(self->pkgs->packages, pkgname);
|
|
if (!cpkg) {
|
|
PyErr_SetString(PyExc_ValueError, "Not a valid package");
|
|
}
|
|
return cpkg;
|
|
}
|
|
|
|
static PyObject *dpkgpackages_ispresent(dpkgpackages *self, PyObject *args) {
|
|
dpkg_collected_package *cpkg;
|
|
char *pkgname;
|
|
if (!PyArg_ParseTuple(args, "s", &pkgname)) return NULL;
|
|
cpkg = lookup_packagetbl(self->pkgs->packages, pkgname);
|
|
return cpkg ? Py_BuildValue("i", 1) : Py_BuildValue("i", 0);
|
|
}
|
|
|
|
static PyObject *dpkgpackages_getversion(dpkgpackages *self, PyObject *args) {
|
|
dpkg_collected_package *cpkg;
|
|
char *pkgname;
|
|
if (!PyArg_ParseTuple(args, "s", &pkgname)) return NULL;
|
|
cpkg = lookup_packagetbl(self->pkgs->packages, pkgname);
|
|
if (cpkg) return Py_BuildValue("s", cpkg->pkg->version);
|
|
else return Py_BuildValue("");
|
|
}
|
|
static PyObject *dpkgpackages_getsource(dpkgpackages *self, PyObject *args) {
|
|
dpkg_collected_package *cpkg;
|
|
char *pkgname;
|
|
if (!PyArg_ParseTuple(args, "s", &pkgname)) return NULL;
|
|
cpkg = lookup_packagetbl(self->pkgs->packages, pkgname);
|
|
if (cpkg) return Py_BuildValue("s", cpkg->pkg->source);
|
|
else return Py_BuildValue("");
|
|
}
|
|
static PyObject *dpkgpackages_getsourcever(dpkgpackages *self, PyObject *args) {
|
|
dpkg_collected_package *cpkg;
|
|
char *pkgname;
|
|
if (!PyArg_ParseTuple(args, "s", &pkgname)) return NULL;
|
|
cpkg = lookup_packagetbl(self->pkgs->packages, pkgname);
|
|
if (cpkg) return Py_BuildValue("s", cpkg->pkg->source_ver);
|
|
else return Py_BuildValue("");
|
|
}
|
|
static PyObject *dpkgpackages_isarchall(dpkgpackages *self, PyObject *args) {
|
|
dpkg_collected_package *cpkg;
|
|
char *pkgname;
|
|
if (!PyArg_ParseTuple(args, "s", &pkgname)) return NULL;
|
|
cpkg = lookup_packagetbl(self->pkgs->packages, pkgname);
|
|
if (cpkg) return Py_BuildValue("i", cpkg->pkg->arch_all);
|
|
else return Py_BuildValue("");
|
|
}
|
|
static PyObject *dpkgpackages_isntarchall(dpkgpackages *self, PyObject *args) {
|
|
dpkg_collected_package *cpkg;
|
|
char *pkgname;
|
|
if (!PyArg_ParseTuple(args, "s", &pkgname)) return NULL;
|
|
cpkg = lookup_packagetbl(self->pkgs->packages, pkgname);
|
|
if (cpkg) return Py_BuildValue("i", !cpkg->pkg->arch_all);
|
|
else return Py_BuildValue("");
|
|
}
|
|
static PyObject *dpkgpackages_getfield(dpkgpackages *self, PyObject *args) {
|
|
char *field;
|
|
char *pkgname;
|
|
int i;
|
|
dpkg_collected_package *cpkg;
|
|
dpkg_paragraph *para;
|
|
if (!PyArg_ParseTuple(args, "ss", &pkgname, &field)) return NULL;
|
|
cpkg = dpkgpackages_lookuppkg(self, pkgname);
|
|
if (!cpkg) return NULL;
|
|
para = cpkg->pkg->details;
|
|
for (i = 0; i < para->n_entries; i++) {
|
|
if (strcasecmp(para->entry[i].name, field) == 0) {
|
|
return Py_BuildValue("s", para->entry[i].value);
|
|
}
|
|
}
|
|
return Py_BuildValue("");
|
|
}
|
|
static PyObject *dpkgpackages_isinstallable(dpkgpackages *self, PyObject *args)
|
|
{
|
|
char *pkgname;
|
|
if (!PyArg_ParseTuple(args, "s", &pkgname)) return NULL;
|
|
if (checkinstallable2(self->pkgs, pkgname)) {
|
|
return Py_BuildValue("i", 1);
|
|
} else {
|
|
return Py_BuildValue("");
|
|
}
|
|
}
|
|
static PyObject *dpkgpackages_isuninstallable(dpkgpackages *self,
|
|
PyObject *args)
|
|
{
|
|
char *pkgname;
|
|
if (!PyArg_ParseTuple(args, "s", &pkgname)) return NULL;
|
|
if (!checkinstallable2(self->pkgs, pkgname)) {
|
|
return Py_BuildValue("i", 1);
|
|
} else {
|
|
return Py_BuildValue("");
|
|
}
|
|
}
|
|
static PyObject *dpkgpackages_unsatdeps(dpkgpackages *self, PyObject *args) {
|
|
/* arguments are:
|
|
* testingpkgs[arch].unsatisfiable_deps(unstablepkgs[arch], "netbase", "Depends")
|
|
* exciting, huh?
|
|
*/
|
|
|
|
dpkgpackages *pkgpkgs;
|
|
char *pkgname, *fieldname;
|
|
dpkg_collected_package *cpkg;
|
|
int fieldidx;
|
|
int buflen = 100;
|
|
char *buf = malloc(buflen);
|
|
const char *fields[] = { "Pre-Depends", "Depends", "Recommends",
|
|
"Suggests", NULL };
|
|
satisfieddeplist *unsatdeps, *dl;
|
|
PyObject *res = Py_BuildValue("[]");
|
|
|
|
if (!PyArg_ParseTuple(args, "O!ss", &Packages_Type, &pkgpkgs, &pkgname, &fieldname)) return NULL;
|
|
|
|
cpkg = lookup_packagetbl(pkgpkgs->pkgs->packages, pkgname);
|
|
if (!cpkg) {
|
|
PyErr_SetString(PyExc_ValueError, "Not a valid package");
|
|
return NULL;
|
|
}
|
|
|
|
for (fieldidx = 0; fields[fieldidx]; fieldidx++) {
|
|
if (strcmp(fields[fieldidx], fieldname) == 0) break;
|
|
}
|
|
if (!fields[fieldidx]) {
|
|
PyErr_SetString(PyExc_ValueError, "Not a valid dependency field");
|
|
return NULL;
|
|
}
|
|
|
|
unsatdeps = checkunsatisfiabledeps(self->pkgs,
|
|
cpkg->pkg->depends[fieldidx]);
|
|
for (dl = unsatdeps; dl != NULL; dl = dl->next) {
|
|
int len;
|
|
packagelist *it;
|
|
PyObject *pkglist;
|
|
deplist *depl;
|
|
dependency *dep;
|
|
|
|
len = 0;
|
|
buf[0] = '\0';
|
|
for (depl = dl->value->depl; depl; depl = depl->next) {
|
|
dep = depl->value;
|
|
len += strlen(dep->package) + 4;
|
|
/* 4 = strlen(" | ") + 1 */
|
|
if (dep->op != dr_NOOP) {
|
|
len += strlen(dep->version) + 6;
|
|
/* 6 = strlen(" (>= )") */
|
|
}
|
|
if (len >= buflen) {
|
|
char *newbuf;
|
|
newbuf = realloc(buf, len + 100);
|
|
if (newbuf == NULL) {
|
|
free_satisfieddeplist(unsatdeps);
|
|
free(buf);
|
|
Py_DECREF(res);
|
|
PyErr_SetFromErrno(PyExc_MemoryError);
|
|
return NULL;
|
|
}
|
|
buf = newbuf;
|
|
buflen = len + 100;
|
|
}
|
|
if (buf[0] != '\0') strcat(buf, " | ");
|
|
strcat(buf, dep->package);
|
|
if (dep->op != dr_NOOP) {
|
|
sprintf(buf + strlen(buf), " (%s %s)",
|
|
dependency_relation_sym[dep->op],
|
|
dep->version);
|
|
}
|
|
}
|
|
|
|
MAKE_PY_LIST(pkglist, it = dl->value->pkgs, it, it = it->next,
|
|
("s", it->value->package)
|
|
);
|
|
|
|
{
|
|
PyObject *depel = Py_BuildValue("(sN)", buf, pkglist);
|
|
PyList_Append(res, depel);
|
|
Py_DECREF(depel);
|
|
}
|
|
}
|
|
|
|
free_satisfieddeplist(unsatdeps);
|
|
free(buf);
|
|
|
|
return res;
|
|
}
|
|
|
|
|
|
static PyObject *dpkgpackages_remove_binary(dpkgpackages *self, PyObject *args) {
|
|
char *pkg_name;
|
|
|
|
(void)self; /* unused */
|
|
|
|
if (!PyArg_ParseTuple(args, "s", &pkg_name))
|
|
return NULL;
|
|
|
|
dpkg_collected_package *cpkg = lookup_packagetbl(self->pkgs->packages, pkg_name);
|
|
if (cpkg == NULL) return Py_BuildValue("i", 0);
|
|
|
|
remove_package(self->pkgs, cpkg);
|
|
return Py_BuildValue("i", 1);
|
|
}
|
|
|
|
static PyObject *dpkgpackages_add_binary(dpkgpackages *self, PyObject *args) {
|
|
char *pkg_name;
|
|
PyObject *value, *pyString;
|
|
|
|
(void)self; /* unused */
|
|
|
|
if (!PyArg_ParseTuple(args, "sO", &pkg_name, &value) ||
|
|
!PyList_Check(value)) return NULL;
|
|
|
|
/* initialize the new package */
|
|
dpkg_package *pkg;
|
|
pkg = block_malloc(sizeof(dpkg_package));
|
|
pkg->package = strdup(pkg_name);
|
|
pkg->priority = 0;
|
|
pkg->details = NULL;
|
|
pkg->depends[2] = NULL;
|
|
pkg->depends[3] = NULL;
|
|
|
|
pyString = PyList_GetItem(value, 0);
|
|
if (pyString == NULL) return NULL;
|
|
pkg->version = PyString_AsString(pyString);
|
|
|
|
pyString = PyList_GetItem(value, 2);
|
|
if (pyString == NULL) return NULL;
|
|
pkg->source = PyString_AsString(pyString);
|
|
|
|
pyString = PyList_GetItem(value, 3);
|
|
if (pyString == NULL) return NULL;
|
|
pkg->source_ver = PyString_AsString(pyString);
|
|
|
|
pyString = PyList_GetItem(value, 4);
|
|
if (pyString == NULL) return NULL;
|
|
pkg->arch_all = (pyString == Py_None || strcmp(PyString_AsString(pyString), "all") ? 0 : 1);
|
|
|
|
pyString = PyList_GetItem(value, 5);
|
|
if (pyString == NULL) return NULL;
|
|
if (pyString != Py_None) {
|
|
pkg->depends[0] = read_dep_andor(PyString_AsString(pyString));
|
|
} else pkg->depends[0] = NULL;
|
|
|
|
pyString = PyList_GetItem(value, 6);
|
|
if (pyString == NULL) return NULL;
|
|
if (pyString != Py_None) {
|
|
pkg->depends[1] = read_dep_andor(PyString_AsString(pyString));
|
|
} else pkg->depends[1] = NULL;
|
|
|
|
pyString = PyList_GetItem(value, 7);
|
|
if (pyString == NULL) return NULL;
|
|
if (pyString != Py_None) {
|
|
pkg->conflicts = read_dep_and(PyString_AsString(pyString));
|
|
} else pkg->conflicts = NULL;
|
|
|
|
pyString = PyList_GetItem(value, 8);
|
|
if (pyString == NULL) return NULL;
|
|
if (pyString != Py_None) {
|
|
pkg->provides = read_packagenames(PyString_AsString(pyString));
|
|
} else pkg->provides = NULL;
|
|
|
|
add_package(self->pkgs, pkg);
|
|
|
|
return Py_BuildValue("i", 1);
|
|
}
|
|
|
|
static PyObject *dpkgpackages_getattr(dpkgpackages *self, char *name) {
|
|
static struct PyMethodDef dpkgsources_methods[] = {
|
|
{ "is_present", (binaryfunc) dpkgpackages_ispresent,
|
|
METH_VARARGS, NULL },
|
|
{ "get_version", (binaryfunc) dpkgpackages_getversion,
|
|
METH_VARARGS, NULL },
|
|
{ "get_source", (binaryfunc) dpkgpackages_getsource,
|
|
METH_VARARGS, NULL },
|
|
{ "get_sourcever", (binaryfunc) dpkgpackages_getsourcever,
|
|
METH_VARARGS, NULL },
|
|
{ "is_arch_all", (binaryfunc) dpkgpackages_isarchall,
|
|
METH_VARARGS, NULL },
|
|
{ "isnt_arch_all", (binaryfunc) dpkgpackages_isntarchall,
|
|
METH_VARARGS, NULL },
|
|
{ "get_field", (binaryfunc) dpkgpackages_getfield,
|
|
METH_VARARGS, NULL },
|
|
{ "is_installable", (binaryfunc) dpkgpackages_isinstallable,
|
|
METH_VARARGS, NULL },
|
|
{ "is_uninstallable", (binaryfunc)dpkgpackages_isuninstallable,
|
|
METH_VARARGS, NULL },
|
|
{ "unsatisfiable_deps", (binaryfunc) dpkgpackages_unsatdeps,
|
|
METH_VARARGS, NULL },
|
|
|
|
{ "remove_binary", (binaryfunc) dpkgpackages_remove_binary,
|
|
METH_VARARGS, NULL },
|
|
{ "add_binary", (binaryfunc) dpkgpackages_add_binary,
|
|
METH_VARARGS, NULL },
|
|
|
|
{ NULL, NULL, 0, NULL }
|
|
};
|
|
|
|
if (strcmp(name, "packages") == 0) {
|
|
PyObject *packages;
|
|
packagetbl_iter it;
|
|
MAKE_PY_LIST(packages,
|
|
it = first_packagetbl(self->pkgs->packages),
|
|
!done_packagetbl(it), it = next_packagetbl(it),
|
|
("s", it.k)
|
|
);
|
|
return packages;
|
|
}
|
|
|
|
return Py_FindMethod(dpkgsources_methods, (PyObject *)self, name);
|
|
}
|
|
|
|
static PyTypeObject Packages_Type = {
|
|
PyObject_HEAD_INIT(&PyType_Type)
|
|
|
|
0, /* ob_size (0) */
|
|
"Packages", /* type name */
|
|
sizeof(dpkgpackages), /* basicsize */
|
|
0, /* itemsize (0) */
|
|
|
|
(destructor) dpkgpackages_dealloc,
|
|
(printfunc) 0,
|
|
(getattrfunc) dpkgpackages_getattr,
|
|
(setattrfunc) 0,
|
|
(cmpfunc) 0,
|
|
(reprfunc) 0,
|
|
|
|
0, /* number methods */
|
|
0, /* sequence methods */
|
|
0, /* mapping methods */
|
|
|
|
(hashfunc) 0, /* dict[x] ?? */
|
|
(ternaryfunc) 0, /* x() */
|
|
(reprfunc) 0 /* str(x) */
|
|
};
|
|
|
|
/**************************************************************************
|
|
* britney.Sources -- dpkg_sources wrapper
|
|
*****************************************/
|
|
|
|
typedef struct {
|
|
PyObject_HEAD
|
|
dpkg_sources *srcs;
|
|
} dpkgsources;
|
|
|
|
staticforward PyTypeObject Sources_Type;
|
|
|
|
static PyObject *dpkgsources_new(PyObject *self, PyObject *args) {
|
|
dpkgsources *res = NULL;
|
|
char *dir;
|
|
PyObject *arches;
|
|
char **archesStr = NULL;
|
|
int i, count;
|
|
|
|
(void)self; /* unused */
|
|
|
|
if (!PyArg_ParseTuple(args, "sO!", &dir, &PyList_Type, &arches)) {
|
|
goto end;
|
|
}
|
|
|
|
count = PyList_Size(arches);
|
|
if (count <= 0) {
|
|
PyErr_SetString(PyExc_TypeError, "No architectures specified");
|
|
goto end;
|
|
}
|
|
|
|
archesStr = malloc(sizeof(char *) * count);
|
|
if (!archesStr) {
|
|
PyErr_SetFromErrno(PyExc_MemoryError);
|
|
goto end;
|
|
}
|
|
|
|
for (i = 0; i < count; i++) {
|
|
PyObject *arch = PyList_GetItem(arches, i);
|
|
if (!PyString_Check(arch)) {
|
|
goto end;
|
|
}
|
|
archesStr[i] = PyString_AsString(arch);
|
|
}
|
|
|
|
res = PyObject_NEW(dpkgsources, &Sources_Type);
|
|
if (res == NULL) goto end;
|
|
|
|
res->srcs = read_directory(dir, count, archesStr);
|
|
if (!res->srcs) {
|
|
Py_DECREF(res);
|
|
res = NULL;
|
|
goto end;
|
|
}
|
|
|
|
end:
|
|
if (archesStr) free(archesStr);
|
|
return (PyObject *) res;
|
|
}
|
|
|
|
static void dpkgsources_dealloc(dpkgsources *self) {
|
|
free_sources(self->srcs);
|
|
self->srcs = NULL;
|
|
PyObject_DEL(self);
|
|
}
|
|
|
|
static PyObject *dpkgsources_packages(dpkgsources *self, PyObject *args)
|
|
{
|
|
char *arch;
|
|
dpkg_packages *pkgs;
|
|
if (!PyArg_ParseTuple(args, "s", &arch)) return NULL;
|
|
pkgs = get_architecture(self->srcs, arch);
|
|
return dpkgpackages_new(pkgs, FREE, (PyObject *) self);
|
|
}
|
|
|
|
static PyObject *dpkgsources_isfake(dpkgsources *self, PyObject *args) {
|
|
char *srcname;
|
|
dpkg_source *src;
|
|
|
|
if (!PyArg_ParseTuple(args, "s", &srcname)) return NULL;
|
|
src = lookup_sourcetbl(self->srcs->sources, srcname);
|
|
if (src) return Py_BuildValue("i", src->fake);
|
|
else return Py_BuildValue("");
|
|
}
|
|
|
|
static PyObject *dpkgsources_getversion(dpkgsources *self, PyObject *args) {
|
|
char *srcname;
|
|
dpkg_source *src;
|
|
|
|
if (!PyArg_ParseTuple(args, "s", &srcname)) return NULL;
|
|
src = lookup_sourcetbl(self->srcs->sources, srcname);
|
|
if (src) return Py_BuildValue("s", src->version);
|
|
else return Py_BuildValue("");
|
|
}
|
|
|
|
static PyObject *dpkgsources_getfield(dpkgsources *self, PyObject *args) {
|
|
char *srcname, *field;
|
|
dpkg_source *src;
|
|
int i;
|
|
dpkg_paragraph *para;
|
|
|
|
if (!PyArg_ParseTuple(args, "ss", &srcname, &field)) return NULL;
|
|
src = lookup_sourcetbl(self->srcs->sources, srcname);
|
|
if (!src) {
|
|
PyErr_SetString(PyExc_ValueError, "Not a valid source package");
|
|
return NULL;
|
|
}
|
|
para = src->details;
|
|
if (para) {
|
|
for (i = 0; i < para->n_entries; i++) {
|
|
if (strcasecmp(para->entry[i].name, field) == 0) {
|
|
return Py_BuildValue("s", para->entry[i].value);
|
|
}
|
|
}
|
|
}
|
|
return Py_BuildValue("");
|
|
}
|
|
|
|
static PyObject *dpkgsources_ispresent(dpkgsources *self, PyObject *args) {
|
|
char *srcname;
|
|
if (!PyArg_ParseTuple(args, "s", &srcname)) return NULL;
|
|
if (lookup_sourcetbl(self->srcs->sources, srcname)) {
|
|
return Py_BuildValue("i", 1);
|
|
} else {
|
|
return Py_BuildValue("i", 0);
|
|
}
|
|
}
|
|
|
|
static PyObject *dpkgsources_binaries(dpkgsources *self, PyObject *args) {
|
|
char *srcname, *arch;
|
|
int archnum;
|
|
dpkg_source *src;
|
|
PyObject *res;
|
|
ownedpackagelist *p;
|
|
|
|
if (!PyArg_ParseTuple(args, "ss", &srcname, &arch)) return NULL;
|
|
|
|
for (archnum = 0; archnum < self->srcs->n_arches; archnum++) {
|
|
if (strcmp(arch, self->srcs->archname[archnum]) == 0) break;
|
|
}
|
|
if (archnum == self->srcs->n_arches) {
|
|
PyErr_SetString(PyExc_ValueError, "Not a valid architecture");
|
|
return NULL;
|
|
}
|
|
|
|
src = lookup_sourcetbl(self->srcs->sources, srcname);
|
|
if (src == NULL) {
|
|
PyErr_SetString(PyExc_ValueError, "Not a valid source package");
|
|
return NULL;
|
|
}
|
|
|
|
MAKE_PY_LIST(res, p = src->packages[archnum], p, p = p->next,
|
|
("s", p->value->package)
|
|
);
|
|
return res;
|
|
}
|
|
|
|
static PyObject *dpkgsources_getattr(dpkgsources *self, char *name) {
|
|
static struct PyMethodDef dpkgsources_methods[] = {
|
|
{ "Packages", (binaryfunc) dpkgsources_packages,
|
|
METH_VARARGS, NULL },
|
|
{ "is_fake", (binaryfunc) dpkgsources_isfake,
|
|
METH_VARARGS, NULL },
|
|
{ "get_version", (binaryfunc) dpkgsources_getversion,
|
|
METH_VARARGS, NULL },
|
|
{ "get_field", (binaryfunc) dpkgsources_getfield,
|
|
METH_VARARGS, NULL },
|
|
{ "is_present", (binaryfunc) dpkgsources_ispresent,
|
|
METH_VARARGS, NULL },
|
|
{ "binaries", (binaryfunc) dpkgsources_binaries,
|
|
METH_VARARGS, NULL },
|
|
{ NULL, NULL, 0, NULL }
|
|
};
|
|
|
|
if (strcmp(name, "arches") == 0) {
|
|
PyObject *arches;
|
|
int i;
|
|
MAKE_PY_LIST(arches, i = 0, i < self->srcs->n_arches, i++,
|
|
("s", self->srcs->archname[i])
|
|
);
|
|
return arches;
|
|
} else if (strcmp(name, "sources") == 0) {
|
|
PyObject *sources;
|
|
sourcetbl_iter it;
|
|
MAKE_PY_LIST(sources,
|
|
it = first_sourcetbl(self->srcs->sources),
|
|
!done_sourcetbl(it), it = next_sourcetbl(it),
|
|
("s", it.k)
|
|
);
|
|
return sources;
|
|
}
|
|
|
|
return Py_FindMethod(dpkgsources_methods, (PyObject *)self, name);
|
|
}
|
|
|
|
static PyTypeObject Sources_Type = {
|
|
PyObject_HEAD_INIT(&PyType_Type)
|
|
|
|
0, /* ob_size (0) */
|
|
"Sources", /* type name */
|
|
sizeof(dpkgsources), /* basicsize */
|
|
0, /* itemsize (0) */
|
|
|
|
(destructor) dpkgsources_dealloc,
|
|
(printfunc) 0,
|
|
(getattrfunc) dpkgsources_getattr,
|
|
(setattrfunc) 0,
|
|
(cmpfunc) 0,
|
|
(reprfunc) 0,
|
|
|
|
0, /* number methods */
|
|
0, /* sequence methods */
|
|
0, /* mapping methods */
|
|
|
|
(hashfunc) 0, /* dict[x] ?? */
|
|
(ternaryfunc) 0, /* x() */
|
|
(reprfunc) 0 /* str(x) */
|
|
};
|
|
|
|
/**************************************************************************
|
|
* britney.SourcesNote -- dpkg_sourcesnote wrapper
|
|
*************************************************/
|
|
|
|
typedef struct {
|
|
PyObject_HEAD
|
|
dpkg_sources_note *srcsn;
|
|
PyObject *refs; /* list of referenced dpkgsources */
|
|
} dpkgsrcsn;
|
|
|
|
staticforward PyTypeObject SourcesNote_Type;
|
|
|
|
static PyObject *dpkgsrcsn_new(PyObject *self, PyObject *args) {
|
|
dpkgsrcsn *res = NULL;
|
|
PyObject *arches;
|
|
char **archesStr = NULL;
|
|
int i, count;
|
|
|
|
(void)self; /* unused */
|
|
|
|
if (!PyArg_ParseTuple(args, "O!", &PyList_Type, &arches)) {
|
|
goto end;
|
|
}
|
|
|
|
count = PyList_Size(arches);
|
|
if (count <= 0) {
|
|
PyErr_SetString(PyExc_TypeError, "No architectures specified");
|
|
goto end;
|
|
}
|
|
|
|
archesStr = malloc(sizeof(char *) * count);
|
|
if (!archesStr) {
|
|
PyErr_SetFromErrno(PyExc_MemoryError);
|
|
goto end;
|
|
}
|
|
|
|
for (i = 0; i < count; i++) {
|
|
PyObject *arch = PyList_GetItem(arches, i);
|
|
if (!PyString_Check(arch)) {
|
|
goto end;
|
|
}
|
|
archesStr[i] = PyString_AsString(arch);
|
|
}
|
|
|
|
res = PyObject_NEW(dpkgsrcsn, &SourcesNote_Type);
|
|
if (res == NULL) goto end;
|
|
|
|
res->refs = PyList_New(0);
|
|
res->srcsn = new_sources_note(count, archesStr);
|
|
if (!res->refs || !res->srcsn) {
|
|
Py_DECREF(res);
|
|
res = NULL;
|
|
goto end;
|
|
}
|
|
|
|
end:
|
|
if (archesStr) free(archesStr);
|
|
return (PyObject *) res;
|
|
}
|
|
|
|
static void dpkgsrcsn_dealloc(dpkgsrcsn *self) {
|
|
if (self->srcsn) free_sources_note(self->srcsn);
|
|
self->srcsn = NULL;
|
|
Py_XDECREF(self->refs);
|
|
self->refs = NULL;
|
|
|
|
PyObject_DEL(self);
|
|
}
|
|
|
|
static PyObject *dpkgsrcsn_removesource(dpkgsrcsn *self, PyObject *args) {
|
|
char *name;
|
|
if (!PyArg_ParseTuple(args, "s", &name)) return NULL;
|
|
remove_source(self->srcsn, name);
|
|
return Py_BuildValue("");
|
|
}
|
|
static PyObject *dpkgsrcsn_upgradesource(dpkgsrcsn *self, PyObject *args) {
|
|
char *name;
|
|
dpkgsources *srcs;
|
|
dpkg_source *src;
|
|
if (!PyArg_ParseTuple(args, "O!s", &Sources_Type, &srcs, &name))
|
|
return NULL;
|
|
src = lookup_sourcetbl(srcs->srcs->sources, name);
|
|
if (!src) {
|
|
PyErr_SetString(PyExc_ValueError, "Source does not exist");
|
|
return NULL;
|
|
}
|
|
if (!PySequence_In(self->refs, (PyObject *)srcs))
|
|
PyList_Append(self->refs, (PyObject *)srcs);
|
|
upgrade_source(self->srcsn, src);
|
|
return Py_BuildValue("");
|
|
}
|
|
static PyObject *dpkgsrcsn_upgradearch(dpkgsrcsn *self, PyObject *args) {
|
|
char *name, *arch;
|
|
dpkgsources *srcs;
|
|
dpkg_source *src;
|
|
if (!PyArg_ParseTuple(args, "O!ss", &Sources_Type, &srcs, &name, &arch))
|
|
return NULL;
|
|
src = lookup_sourcetbl(srcs->srcs->sources, name);
|
|
if (!src) {
|
|
PyErr_SetString(PyExc_ValueError, "Source does not exist");
|
|
return NULL;
|
|
}
|
|
if (!PySequence_In(self->refs, (PyObject *)srcs))
|
|
PyList_Append(self->refs, (PyObject *)srcs);
|
|
upgrade_arch(self->srcsn, src, arch);
|
|
return Py_BuildValue("");
|
|
}
|
|
|
|
static PyObject *dpkgsrcsn_undochange(dpkgsrcsn *self, PyObject *args) {
|
|
if (!PyArg_ParseTuple(args, "")) return NULL;
|
|
undo_change(self->srcsn);
|
|
return Py_BuildValue("");
|
|
}
|
|
|
|
static PyObject *dpkgsrcsn_commitchanges(dpkgsrcsn *self, PyObject *args) {
|
|
if (!PyArg_ParseTuple(args, "")) return NULL;
|
|
commit_changes(self->srcsn);
|
|
return Py_BuildValue("");
|
|
}
|
|
|
|
static PyObject *dpkgsrcsn_writenotes(dpkgsrcsn *self, PyObject *args) {
|
|
char *dir;
|
|
if (!PyArg_ParseTuple(args, "s", &dir)) return NULL;
|
|
write_notes(dir, self->srcsn);
|
|
return Py_BuildValue("");
|
|
}
|
|
|
|
static PyObject *dpkgsrcsn_packages(dpkgsrcsn *self, PyObject *args) {
|
|
char *arch;
|
|
int archnum;
|
|
if (!PyArg_ParseTuple(args, "s", &arch)) return NULL;
|
|
for (archnum = 0; archnum < self->srcsn->n_arches; archnum++) {
|
|
if (strcmp(arch, self->srcsn->archname[archnum]) == 0) break;
|
|
}
|
|
if (archnum == self->srcsn->n_arches) {
|
|
PyErr_SetString(PyExc_ValueError, "Not a valid architecture");
|
|
return NULL;
|
|
}
|
|
return dpkgpackages_new(self->srcsn->pkgs[archnum], DONTFREE,
|
|
(PyObject *) self);
|
|
}
|
|
|
|
static PyObject *dpkgsrcsn_getversion(dpkgsrcsn *self, PyObject *args) {
|
|
char *srcname;
|
|
dpkg_source_note *srcn;
|
|
|
|
if (!PyArg_ParseTuple(args, "s", &srcname)) return NULL;
|
|
srcn = lookup_sourcenotetbl(self->srcsn->sources, srcname);
|
|
if (srcn) return Py_BuildValue("s", srcn->source->version);
|
|
else return Py_BuildValue("");
|
|
}
|
|
static PyObject *dpkgsrcsn_getfield(dpkgsrcsn *self, PyObject *args) {
|
|
char *srcname, *field;
|
|
dpkg_source_note *srcn;
|
|
int i;
|
|
dpkg_paragraph *para;
|
|
|
|
if (!PyArg_ParseTuple(args, "ss", &srcname, &field)) return NULL;
|
|
srcn = lookup_sourcenotetbl(self->srcsn->sources, srcname);
|
|
if (!srcn) {
|
|
PyErr_SetString(PyExc_ValueError, "Not a valid source package");
|
|
return NULL;
|
|
}
|
|
para = srcn->source->details;
|
|
if (para) {
|
|
for (i = 0; i < para->n_entries; i++) {
|
|
if (strcasecmp(para->entry[i].name, field) == 0) {
|
|
return Py_BuildValue("s", para->entry[i].value);
|
|
}
|
|
}
|
|
}
|
|
return Py_BuildValue("");
|
|
}
|
|
static PyObject *dpkgsrcsn_ispresent(dpkgsrcsn *self, PyObject *args) {
|
|
char *srcname;
|
|
if (!PyArg_ParseTuple(args, "s", &srcname)) return NULL;
|
|
if (lookup_sourcenotetbl(self->srcsn->sources, srcname)) {
|
|
return Py_BuildValue("i", 1);
|
|
} else {
|
|
return Py_BuildValue("i", 0);
|
|
}
|
|
}
|
|
|
|
static PyObject *dpkgsrcsn_isfake(dpkgsrcsn *self, PyObject *args) {
|
|
char *srcname;
|
|
dpkg_source_note *srcn;
|
|
|
|
if (!PyArg_ParseTuple(args, "s", &srcname)) return NULL;
|
|
srcn = lookup_sourcenotetbl(self->srcsn->sources, srcname);
|
|
if (srcn) return Py_BuildValue("i", srcn->source->fake);
|
|
else return Py_BuildValue("");
|
|
}
|
|
|
|
static PyObject *dpkgsrcsn_binaries(dpkgsrcsn *self, PyObject *args) {
|
|
char *srcname, *arch;
|
|
int archnum;
|
|
dpkg_source_note *srcn;
|
|
PyObject *res;
|
|
packagelist *p;
|
|
|
|
if (!PyArg_ParseTuple(args, "ss", &srcname, &arch)) return NULL;
|
|
|
|
for (archnum = 0; archnum < self->srcsn->n_arches; archnum++) {
|
|
if (strcmp(arch, self->srcsn->archname[archnum]) == 0) break;
|
|
}
|
|
if (archnum == self->srcsn->n_arches) {
|
|
PyErr_SetString(PyExc_ValueError, "Not a valid architecture");
|
|
return NULL;
|
|
}
|
|
|
|
srcn = lookup_sourcenotetbl(self->srcsn->sources, srcname);
|
|
if (srcn == NULL) {
|
|
PyErr_SetString(PyExc_ValueError, "Not a valid source package");
|
|
return NULL;
|
|
}
|
|
|
|
MAKE_PY_LIST(res, p = srcn->binaries[archnum], p, p = p->next,
|
|
("s", p->value->package)
|
|
);
|
|
return res;
|
|
}
|
|
|
|
static PyObject *dpkgsrcsn_getattr(dpkgsrcsn *self, char *name) {
|
|
static struct PyMethodDef dpkgsrcsn_methods[] = {
|
|
{ "remove_source", (binaryfunc) dpkgsrcsn_removesource,
|
|
METH_VARARGS, NULL },
|
|
{ "upgrade_source", (binaryfunc) dpkgsrcsn_upgradesource,
|
|
METH_VARARGS, NULL },
|
|
{ "upgrade_arch", (binaryfunc) dpkgsrcsn_upgradearch,
|
|
METH_VARARGS, NULL },
|
|
|
|
{ "undo_change", (binaryfunc) dpkgsrcsn_undochange,
|
|
METH_VARARGS, NULL },
|
|
{ "commit_changes", (binaryfunc) dpkgsrcsn_commitchanges,
|
|
METH_VARARGS, NULL },
|
|
|
|
{ "write_notes", (binaryfunc) dpkgsrcsn_writenotes,
|
|
METH_VARARGS, NULL },
|
|
|
|
{ "Packages", (binaryfunc) dpkgsrcsn_packages,
|
|
METH_VARARGS, NULL },
|
|
|
|
{ "get_version", (binaryfunc) dpkgsrcsn_getversion,
|
|
METH_VARARGS, NULL },
|
|
{ "get_field", (binaryfunc) dpkgsrcsn_getfield,
|
|
METH_VARARGS, NULL },
|
|
{ "is_present", (binaryfunc) dpkgsrcsn_ispresent,
|
|
METH_VARARGS, NULL },
|
|
{ "is_fake", (binaryfunc) dpkgsrcsn_isfake,
|
|
METH_VARARGS, NULL },
|
|
{ "binaries", (binaryfunc) dpkgsrcsn_binaries,
|
|
METH_VARARGS, NULL },
|
|
{ NULL, NULL, 0, NULL }
|
|
};
|
|
|
|
if (strcmp(name, "arches") == 0) {
|
|
PyObject *arches;
|
|
int i;
|
|
MAKE_PY_LIST(arches, i = 0, i < self->srcsn->n_arches, i++,
|
|
("s", self->srcsn->archname[i])
|
|
);
|
|
return arches;
|
|
} else if (strcmp(name, "sources") == 0) {
|
|
PyObject *sources;
|
|
sourcenotetbl_iter it;
|
|
MAKE_PY_LIST(sources,
|
|
it = first_sourcenotetbl(self->srcsn->sources),
|
|
!done_sourcenotetbl(it),
|
|
it = next_sourcenotetbl(it),
|
|
("s", it.k)
|
|
);
|
|
return sources;
|
|
} else if (strcmp(name, "can_undo") == 0) {
|
|
if (can_undo(self->srcsn)) {
|
|
return Py_BuildValue("i", 1);
|
|
} else {
|
|
return Py_BuildValue("");
|
|
}
|
|
}
|
|
|
|
return Py_FindMethod(dpkgsrcsn_methods, (PyObject *)self, name);
|
|
}
|
|
|
|
static PyTypeObject SourcesNote_Type = {
|
|
PyObject_HEAD_INIT(&PyType_Type)
|
|
|
|
0, /* ob_size (0) */
|
|
"SourcesNote", /* type name */
|
|
sizeof(dpkgsrcsn), /* basicsize */
|
|
0, /* itemsize (0) */
|
|
|
|
(destructor) dpkgsrcsn_dealloc,
|
|
(printfunc) 0,
|
|
(getattrfunc) dpkgsrcsn_getattr,
|
|
(setattrfunc) 0,
|
|
(cmpfunc) 0,
|
|
(reprfunc) 0,
|
|
|
|
0, /* number methods */
|
|
0, /* sequence methods */
|
|
0, /* mapping methods */
|
|
|
|
(hashfunc) 0, /* dict[x] ?? */
|
|
(ternaryfunc) 0, /* x() */
|
|
(reprfunc) 0 /* str(x) */
|
|
};
|
|
|
|
/**************************************************************************
|
|
* britney.versioncmp() -- apt version compare function
|
|
******************************************************/
|
|
|
|
static PyObject *apt_versioncmp(PyObject *self, PyObject *args) {
|
|
char *l, *r;
|
|
int res;
|
|
|
|
(void)self; /* unused */
|
|
|
|
if (!PyArg_ParseTuple(args, "ss", &l, &r)) {
|
|
return NULL;
|
|
}
|
|
|
|
res = versioncmp(l,r);
|
|
return Py_BuildValue("i", res);
|
|
}
|
|
|
|
/**************************************************************************
|
|
* britney.buildSystem() -- build a fake package system, with the only purpose of
|
|
* calling the is_installable method on the packages.
|
|
******************************************************/
|
|
|
|
static PyObject *build_system(PyObject *self, PyObject *args) {
|
|
Py_ssize_t pos = 0;
|
|
char *arch;
|
|
PyObject *pkgs, *key, *value, *pyString;
|
|
|
|
(void)self; /* unused */
|
|
|
|
if (!PyArg_ParseTuple(args, "sO", &arch, &pkgs) ||
|
|
!PyDict_Check(pkgs)) return NULL;
|
|
|
|
/* Fields and positions for the binary package:
|
|
# VERSION = 0
|
|
# SECTION = 1
|
|
# SOURCE = 2
|
|
# SOURCEVER = 3
|
|
# ARCHITECTURE = 4
|
|
# PREDEPENDS = 5
|
|
# DEPENDS = 6
|
|
# CONFLICTS = 7
|
|
# PROVIDES = 8
|
|
# RDEPENDS = 9
|
|
# RCONFLICTS = 10
|
|
*/
|
|
|
|
dpkg_packages *dpkg_pkgs = new_packages(arch);
|
|
|
|
/* loop on the dictionary keys to build the packages */
|
|
while (PyDict_Next(pkgs, &pos, &key, &value)) {
|
|
|
|
/* initialize the new package */
|
|
dpkg_package *pkg;
|
|
pkg = block_malloc(sizeof(dpkg_package));
|
|
pkg->package = strdup(PyString_AsString(key));
|
|
pkg->priority = 0;
|
|
pkg->details = NULL;
|
|
pkg->depends[2] = NULL;
|
|
pkg->depends[3] = NULL;
|
|
|
|
pyString = PyList_GetItem(value, 0);
|
|
if (pyString == NULL) continue;
|
|
pkg->version = PyString_AsString(pyString);
|
|
|
|
pyString = PyList_GetItem(value, 2);
|
|
if (pyString == NULL) continue;
|
|
pkg->source = PyString_AsString(pyString);
|
|
|
|
pyString = PyList_GetItem(value, 3);
|
|
if (pyString == NULL) continue;
|
|
pkg->source_ver = PyString_AsString(pyString);
|
|
|
|
pyString = PyList_GetItem(value, 4);
|
|
if (pyString == NULL) continue;
|
|
pkg->arch_all = (pyString == Py_None || strcmp(PyString_AsString(pyString), "all") ? 0 : 1);
|
|
|
|
pyString = PyList_GetItem(value, 5);
|
|
if (pyString == NULL) continue;
|
|
if (pyString != Py_None) {
|
|
pkg->depends[0] = read_dep_andor(PyString_AsString(pyString));
|
|
} else pkg->depends[0] = NULL;
|
|
|
|
pyString = PyList_GetItem(value, 6);
|
|
if (pyString == NULL) continue;
|
|
if (pyString != Py_None) {
|
|
pkg->depends[1] = read_dep_andor(PyString_AsString(pyString));
|
|
} else pkg->depends[1] = NULL;
|
|
|
|
pyString = PyList_GetItem(value, 7);
|
|
if (pyString == NULL) continue;
|
|
if (pyString != Py_None) {
|
|
pkg->conflicts = read_dep_and(PyString_AsString(pyString));
|
|
} else pkg->conflicts = NULL;
|
|
|
|
pyString = PyList_GetItem(value, 8);
|
|
if (pyString == NULL) continue;
|
|
if (pyString != Py_None) {
|
|
pkg->provides = read_packagenames(PyString_AsString(pyString));
|
|
} else pkg->provides = NULL;
|
|
|
|
add_package(dpkg_pkgs, pkg);
|
|
}
|
|
|
|
dpkgpackages *res;
|
|
res = PyObject_NEW(dpkgpackages, &Packages_Type);
|
|
if (res == NULL) return NULL;
|
|
|
|
res->pkgs = dpkg_pkgs;
|
|
res->freeme = FREE;
|
|
res->ref = NULL;
|
|
|
|
return (PyObject *)res;
|
|
}
|
|
|
|
|
|
/**************************************************************************
|
|
* module initialisation
|
|
***********************/
|
|
|
|
static PyMethodDef britneymethods[] = {
|
|
{ "Sources", dpkgsources_new, METH_VARARGS, NULL },
|
|
{ "SourcesNote", dpkgsrcsn_new, METH_VARARGS, NULL },
|
|
|
|
{ "versioncmp", apt_versioncmp, METH_VARARGS, NULL },
|
|
|
|
{ "buildSystem", build_system, METH_VARARGS, NULL },
|
|
|
|
{ NULL, NULL, 0, NULL }
|
|
};
|
|
|
|
void initbritney(void) {
|
|
Py_InitModule("britney", britneymethods);
|
|
}
|
|
|