Modify eu-strip option to perform strip in post script of rpm package & add option...
[platform/upstream/rpm.git] / python / spec-py.c
index 510d6d7..1850a50 100644 (file)
@@ -1,5 +1,6 @@
 #include "rpmsystem-py.h"
 
+#include "header-py.h"
 #include "spec-py.h"
 
 /** \ingroup python
@@ -19,8 +20,7 @@
  * \code
  *  import rpm
  *  rpm.addMacro("_topdir","/path/to/topdir")
- *  ts=rpm.ts()
- *  s=ts.parseSpec("foo.spec")
+ *  s=rpm.spec("foo.spec")
  *  print s.prep()
  * \endcode
  *
  *
  */
 
+/* Header objects are in another module, some hoop jumping required... */
+static PyObject *makeHeader(Header h)
+{
+    PyObject *rpmmod = PyImport_ImportModuleNoBlock("rpm");
+    if (rpmmod == NULL) return NULL;
+
+    PyObject *ptr = CAPSULE_BUILD(h, "rpm._C_Header");
+    PyObject *hdr = PyObject_CallMethod(rpmmod, "hdr", "(O)", ptr);
+    Py_XDECREF(ptr);
+    Py_XDECREF(rpmmod);
+    return hdr;
+}
+
+struct specPkgObject_s {
+    PyObject_HEAD
+    /*type specific fields */
+    rpmSpecPkg pkg;
+};
+
+static char specPkg_doc[] =
+"";
+
+static PyObject * specpkg_get_header(specPkgObject *s, void *closure)
+{
+    return makeHeader(rpmSpecPkgHeader(s->pkg));
+}
+
+static PyGetSetDef specpkg_getseters[] = {
+    { "header",        (getter) specpkg_get_header, NULL, NULL },
+    { NULL }   /* sentinel */
+};
+
+PyTypeObject specPkg_Type = {
+       PyVarObject_HEAD_INIT(&PyType_Type, 0)
+       "rpm.specpkg",                  /* tp_name */
+       sizeof(specPkgObject),          /* tp_size */
+       0,                              /* tp_itemsize */
+       0,                              /* tp_dealloc */
+       0,                              /* tp_print */
+       0,                              /* tp_getattr */
+       0,                              /* tp_setattr */
+       0,                              /* tp_compare */
+       0,                              /* tp_repr */
+       0,                              /* tp_as_number */
+       0,                              /* tp_as_sequence */
+       0,                              /* tp_as_mapping */
+       0,                              /* tp_hash */
+       0,                              /* tp_call */
+       0,                              /* tp_str */
+       PyObject_GenericGetAttr,        /* tp_getattro */
+       PyObject_GenericSetAttr,        /* tp_setattro */
+       0,                              /* tp_as_buffer */
+       Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */
+       specPkg_doc,                    /* tp_doc */
+       0,                              /* tp_traverse */
+       0,                              /* tp_clear */
+       0,                              /* tp_richcompare */
+       0,                              /* tp_weaklistoffset */
+       0,                              /* tp_iter */
+       0,                              /* tp_iternext */
+       0,                              /* tp_methods */
+       0,                              /* tp_members */
+       specpkg_getseters,              /* tp_getset */
+       0,                              /* tp_base */
+       0,                              /* tp_dict */
+       0,                              /* tp_descr_get */
+       0,                              /* tp_descr_set */
+       0,                              /* tp_dictoffset */
+       0,                              /* tp_init */
+       0,                              /* tp_alloc */
+       0,                              /* tp_new */
+       0,                              /* tp_free */
+       0,                              /* tp_is_gc */
+};
+
 struct specObject_s {
     PyObject_HEAD
     /*type specific fields */
@@ -37,125 +112,162 @@ struct specObject_s {
 static void 
 spec_dealloc(specObject * s) 
 {
-        if (s->spec) {
-            s->spec=freeSpec(s->spec);
-        }
-        PyObject_Del(s);
+    if (s->spec) {
+       s->spec=rpmSpecFree(s->spec);
+    }
+    Py_TYPE(s)->tp_free((PyObject *)s);
 }
 
-static int
-spec_print(specObject * s)
+static PyObject * getSection(rpmSpec spec, int section)
 {
-    return 0;
+    const char *sect = rpmSpecGetSection(spec, section);
+    if (sect) {
+       return Py_BuildValue("s", sect);
+    }
+    Py_RETURN_NONE;
 }
 
-/* XXX TODO return something sensible if spec exists but component (eg %clean)
- * does not. Possibly "" or None */
-
 static PyObject * 
-spec_get_buildroot(specObject * s
+spec_get_prep(specObject * s, void *closure
 {
-    rpmSpec spec = specFromSpec(s);
-    if (spec != NULL && spec->buildRoot) {
-        return Py_BuildValue("s", spec->buildRoot);
-    }
-    else {
-        return NULL;
-    }
+    return getSection(s->spec, RPMBUILD_PREP);
 }
 
 static PyObject * 
-spec_get_prep(specObject * s
+spec_get_build(specObject * s, void *closure
 {
-    rpmSpec spec = specFromSpec(s);
-    PyObject *res = NULL;
-    if (spec != NULL && spec->prep) {
-        res = Py_BuildValue("s",getStringBuf(spec->prep));
-    }
-    return res;
+    return getSection(s->spec, RPMBUILD_BUILD);
 }
 
-static PyObject * 
-spec_get_build(specObject * s) 
+static PyObject * spec_get_install(specObject * s, void *closure) 
 {
-    rpmSpec spec = specFromSpec(s);
-    PyObject *res = NULL;
-    if (spec != NULL && spec->build) {
-        res = Py_BuildValue("s",getStringBuf(spec->build));
-    }
-    return res;
+    return getSection(s->spec, RPMBUILD_INSTALL);
 }
 
-static PyObject * 
-spec_get_install(specObject * s) 
+static PyObject * spec_get_clean(specObject * s, void *closure) 
 {
-    rpmSpec spec = specFromSpec(s);
-    PyObject *res = NULL;
-    if (spec != NULL && spec->install) {
-        res = Py_BuildValue("s",getStringBuf(spec->install));
-    }
-    return res;
+    return getSection(s->spec, RPMBUILD_CLEAN);
 }
 
-static PyObject * 
-spec_get_clean(specObject * s) 
+static PyObject * spec_get_sources(specObject *s, void *closure)
 {
-    rpmSpec spec = specFromSpec(s);
-    PyObject *res = NULL;
-    if (spec != NULL && spec->clean) {
-        res = Py_BuildValue("s",getStringBuf(spec->clean));
+    PyObject *sourceList;
+    rpmSpecSrc source;
+
+    sourceList = PyList_New(0);
+    if (!sourceList) {
+        return NULL;
     }
-    return res;
+
+    rpmSpecSrcIter iter = rpmSpecSrcIterInit(s->spec);
+    while ((source = rpmSpecSrcIterNext(iter)) != NULL) {
+       PyObject *srcUrl = Py_BuildValue("(sii)",
+                               rpmSpecSrcFilename(source, 1),
+                               rpmSpecSrcNum(source),
+                               rpmSpecSrcFlags(source)); 
+        if (!srcUrl) {
+            Py_DECREF(sourceList);
+            return NULL;
+        }
+       PyList_Append(sourceList, srcUrl);
+       Py_DECREF(srcUrl);
+    } 
+    rpmSpecSrcIterFree(iter);
+
+    return sourceList;
+
 }
 
-static PyObject *
-spec_get_sources(specObject *s)
+static PyObject * spec_get_packages(specObject *s, void *closure)
 {
-    struct Source * source;
-    PyObject *sourceList, *srcUrl;
-    rpmSpec spec;
-    char * fullSource;
+    rpmSpecPkg pkg;
+    PyObject *pkgList;
+    rpmSpecPkgIter iter;
 
-    sourceList = PyList_New(0);
-    spec = specFromSpec(s);
-    if ( spec != NULL) {
-        source = spec->sources;
-
-         while (source != NULL) {
-            fullSource = source->fullSource;
-            srcUrl = Py_BuildValue("(sii)", fullSource, source->num, source->flags);
-            PyList_Append(sourceList, srcUrl);
-            source=source->next;
-        } 
-
-        return PyList_AsTuple(sourceList);
-    }
-    else {
+    pkgList = PyList_New(0);
+    if (!pkgList) {
         return NULL;
     }
 
+    iter = rpmSpecPkgIterInit(s->spec);
+
+    while ((pkg = rpmSpecPkgIterNext(iter)) != NULL) {
+       PyObject *po = specPkg_Wrap(&specPkg_Type, pkg);
+        if (!po) {
+            rpmSpecPkgIterFree(iter);
+            Py_DECREF(pkgList);
+            return NULL;
+        }
+       PyList_Append(pkgList, po);
+       Py_DECREF(po);
+    }
+    rpmSpecPkgIterFree(iter);
+    return pkgList;
+}
+
+static PyObject * spec_get_source_header(specObject *s, void *closure)
+{
+    return makeHeader(rpmSpecSourceHeader(s->spec));
 }
 
 static char spec_doc[] = "RPM Spec file object";
 
-static PyMethodDef spec_Spec_methods[] = {
-    {"sources",   (PyCFunction) spec_get_sources, METH_VARARGS,  NULL },
-    {"prep",   (PyCFunction) spec_get_prep, METH_VARARGS,  NULL },
-    {"build",   (PyCFunction) spec_get_build, METH_VARARGS,  NULL },
-    {"install",   (PyCFunction) spec_get_install, METH_VARARGS,  NULL },
-    {"clean",   (PyCFunction) spec_get_clean, METH_VARARGS,  NULL },
-    {"buildRoot",   (PyCFunction) spec_get_buildroot, METH_VARARGS,  NULL },
+static PyGetSetDef spec_getseters[] = {
+    {"sources",   (getter) spec_get_sources, NULL, NULL },
+    {"prep",   (getter) spec_get_prep, NULL, NULL },
+    {"build",   (getter) spec_get_build, NULL, NULL },
+    {"install",   (getter) spec_get_install, NULL, NULL },
+    {"clean",   (getter) spec_get_clean, NULL, NULL },
+    {"packages", (getter) spec_get_packages, NULL, NULL },
+    {"sourceHeader", (getter) spec_get_source_header, NULL, NULL },
     {NULL}  /* Sentinel */
 };
 
+static PyObject *spec_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
+{
+    char * kwlist[] = {"specfile", "flags", NULL};
+    const char * specfile;
+    rpmSpec spec = NULL;
+    /* XXX This is a dumb default but anything else breaks compatibility... */
+    rpmSpecFlags flags = (RPMSPEC_ANYARCH|RPMSPEC_FORCE);
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|i:spec_new", kwlist,
+                                    &specfile, &flags))
+       return NULL;
+
+    spec = rpmSpecParse(specfile, flags, NULL);
+    if (spec == NULL) {
+       PyErr_SetString(PyExc_ValueError, "can't parse specfile\n");
+       return NULL;
+    }
+
+    return spec_Wrap(subtype, spec);
+}
+
+static PyObject * spec_doBuild(specObject *self, PyObject *args, PyObject *kwds)
+{
+    char * kwlist[] = { "buildAmount", "pkgFlags", NULL };
+    struct rpmBuildArguments_s ba = { 0 };
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwds, "i|i:spec_doBuild",
+                       kwlist, &ba.buildAmount, &ba.pkgFlags))
+       return NULL;
+
+    return PyBool_FromLong(rpmSpecBuild(self->spec, &ba) == RPMRC_OK);
+}
+
+static struct PyMethodDef spec_methods[] = {
+    { "_doBuild", (PyCFunction)spec_doBuild, METH_VARARGS|METH_KEYWORDS, NULL },
+    { NULL, NULL }
+};
+
 PyTypeObject spec_Type = {
-    PyObject_HEAD_INIT(&PyType_Type)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(&PyType_Type, 0)
     "rpm.spec",               /*tp_name*/
     sizeof(specObject),        /*tp_basicsize*/
     0,                         /*tp_itemsize*/
     (destructor) spec_dealloc, /*tp_dealloc*/
-    (printfunc) spec_print,    /*tp_print*/
+    0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
     0,                         /*tp_compare*/
@@ -169,7 +281,7 @@ PyTypeObject spec_Type = {
     0,                         /*tp_getattro*/
     0,                         /*tp_setattro*/
     0,                         /*tp_as_buffer*/
-    Py_TPFLAGS_DEFAULT,        /*tp_flags*/
+    Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
     spec_doc,                  /* tp_doc */
     0,                         /* tp_traverse */
     0,                         /* tp_clear */
@@ -177,9 +289,9 @@ PyTypeObject spec_Type = {
     0,                         /* tp_weaklistoffset */
     0,                         /* tp_iter */
     0,                         /* tp_iternext */
-    spec_Spec_methods,         /* tp_methods */
+    spec_methods,             /* tp_methods */
     0,                         /* tp_members */
-    0,                         /* tp_getset */
+    spec_getseters,            /* tp_getset */
     0,                         /* tp_base */
     0,                         /* tp_dict */
     0,                         /* tp_descr_get */
@@ -187,22 +299,27 @@ PyTypeObject spec_Type = {
     0,                         /* tp_dictoffset */
     0,                         /* tp_init */
     0,                         /* tp_alloc */
-    0,                         /* tp_new */
+    spec_new,                  /* tp_new */
     0,                         /* tp_free */
     0,                         /* tp_is_gc */
 };
 
-rpmSpec specFromSpec(specObject *s) 
+PyObject *
+spec_Wrap(PyTypeObject *subtype, rpmSpec spec) 
 {
-    return s->spec;
+    specObject * s = (specObject *)subtype->tp_alloc(subtype, 0);
+    if (s == NULL) return NULL;
+
+    s->spec = spec; 
+    return (PyObject *) s;
 }
 
-PyObject *
-spec_Wrap(rpmSpec spec) 
+PyObject * specPkg_Wrap(PyTypeObject *subtype, rpmSpecPkg pkg) 
 {
-    specObject * s = PyObject_New(specObject, &spec_Type);
-    if (s == NULL) return PyErr_NoMemory();
+    specPkgObject * s = (specPkgObject *)subtype->tp_alloc(subtype, 0);
+    if (s == NULL) return NULL;
 
-    s->spec = spec; 
+    s->pkg = pkg;
     return (PyObject *) s;
 }
+