1 #include "rpmsystem-py.h"
5 #include "build/rpmbuild_internal.h" /* XXX FIXME! */
10 * \brief A python rpm.spec object represents an RPM spec file set.
12 * The spec file is at the heart of RPM's packaging building process. Similar
13 * in concept to a makefile, it contains information required by RPM to build
14 * the package, as well as instructions telling RPM how to build it. The spec
15 * file also dictates exactly what files are a part of the package, and where
16 * they should be installed.
18 * The rpm.spec object represents a parsed specfile to aid extraction of data.
23 * rpm.addMacro("_topdir","/path/to/topdir")
24 * s=rpm.spec("foo.spec")
28 * Macros set using add macro will be used allowing testing of conditional builds
32 /* Header objects are in another module, some hoop jumping required... */
33 static PyObject *makeHeader(Header h)
35 PyObject *rpmmod = PyImport_ImportModuleNoBlock("rpm");
36 if (rpmmod == NULL) return NULL;
38 PyObject *ptr = PyCObject_FromVoidPtr(h, NULL);
39 PyObject *hdr = PyObject_CallMethod(rpmmod, "hdr", "(O)", ptr);
45 struct specPkgObject_s {
47 /*type specific fields */
51 static char specPkg_doc[] =
54 static PyObject * specpkg_get_header(specPkgObject *s, void *closure)
56 return makeHeader(rpmSpecPkgHeader(s->pkg));
59 static PyGetSetDef specpkg_getseters[] = {
60 { "header", (getter) specpkg_get_header, NULL, NULL },
61 { NULL } /* sentinel */
64 PyTypeObject specPkg_Type = {
65 PyVarObject_HEAD_INIT(&PyType_Type, 0)
66 "rpm.specpkg", /* tp_name */
67 sizeof(specPkgObject), /* tp_size */
76 0, /* tp_as_sequence */
77 0, /* tp_as_mapping */
81 PyObject_GenericGetAttr, /* tp_getattro */
82 PyObject_GenericSetAttr, /* tp_setattro */
84 Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */
85 specPkg_doc, /* tp_doc */
88 0, /* tp_richcompare */
89 0, /* tp_weaklistoffset */
94 specpkg_getseters, /* tp_getset */
99 0, /* tp_dictoffset */
107 struct specObject_s {
109 /*type specific fields */
114 spec_dealloc(specObject * s)
117 s->spec=rpmSpecFree(s->spec);
119 Py_TYPE(s)->tp_free((PyObject *)s);
123 spec_get_buildroot(specObject * s, void *closure)
125 rpmSpec spec = s->spec;
126 if (spec->buildRoot) {
127 return Py_BuildValue("s", spec->buildRoot);
132 static PyObject * getSection(rpmSpec spec, int section)
134 const char *sect = rpmSpecGetSection(spec, section);
136 return Py_BuildValue("s", sect);
142 spec_get_prep(specObject * s, void *closure)
144 return getSection(s->spec, RPMBUILD_PREP);
148 spec_get_build(specObject * s, void *closure)
150 return getSection(s->spec, RPMBUILD_BUILD);
153 static PyObject * spec_get_install(specObject * s, void *closure)
155 return getSection(s->spec, RPMBUILD_INSTALL);
158 static PyObject * spec_get_clean(specObject * s, void *closure)
160 return getSection(s->spec, RPMBUILD_CLEAN);
163 static PyObject * spec_get_sources(specObject *s, void *closure)
165 PyObject *sourceList = PyList_New(0);
168 rpmSpecSrcIter iter = rpmSpecSrcIterInit(s->spec);
169 while ((source = rpmSpecSrcIterNext(iter)) != NULL) {
170 PyObject *srcUrl = Py_BuildValue("(sii)",
171 rpmSpecSrcFilename(source, 1),
172 rpmSpecSrcNum(source),
173 rpmSpecSrcFlags(source));
174 PyList_Append(sourceList, srcUrl);
177 rpmSpecSrcIterFree(iter);
183 static PyObject * spec_get_packages(specObject *s, void *closure)
186 PyObject *pkgList = PyList_New(0);
187 rpmSpecPkgIter iter = rpmSpecPkgIterInit(s->spec);
189 while ((pkg = rpmSpecPkgIterNext(iter)) != NULL) {
190 PyObject *po = specPkg_Wrap(&specPkg_Type, pkg);
191 PyList_Append(pkgList, po);
194 rpmSpecPkgIterFree(iter);
198 static char spec_doc[] = "RPM Spec file object";
200 static PyGetSetDef spec_getseters[] = {
201 {"sources", (getter) spec_get_sources, NULL, NULL },
202 {"prep", (getter) spec_get_prep, NULL, NULL },
203 {"build", (getter) spec_get_build, NULL, NULL },
204 {"install", (getter) spec_get_install, NULL, NULL },
205 {"clean", (getter) spec_get_clean, NULL, NULL },
206 {"buildRoot", (getter) spec_get_buildroot, NULL, NULL },
207 {"packages", (getter) spec_get_packages, NULL, NULL },
208 {NULL} /* Sentinel */
211 static PyObject *spec_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
213 char * kwlist[] = {"specfile", "flags", NULL};
214 const char * specfile;
216 /* XXX This is a dumb default but anything else breaks compatibility... */
217 rpmSpecFlags flags = (RPMSPEC_ANYARCH|RPMSPEC_FORCE);
219 if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|i:spec_new", kwlist,
223 spec = rpmSpecParse(specfile, flags, NULL);
225 PyErr_SetString(PyExc_ValueError, "can't parse specfile\n");
229 return spec_Wrap(subtype, spec);
232 static PyObject * spec_doBuild(specObject *self, PyObject *args, PyObject *kwds)
234 char * kwlist[] = { "buildAmount", "pkgFlags", NULL };
235 struct rpmBuildArguments_s ba = { 0 };
237 if (!PyArg_ParseTupleAndKeywords(args, kwds, "i|i:spec_doBuild",
238 kwlist, &ba.buildAmount, &ba.pkgFlags))
241 return PyBool_FromLong(rpmSpecBuild(self->spec, &ba) == RPMRC_OK);
244 static struct PyMethodDef spec_methods[] = {
245 { "_doBuild", (PyCFunction)spec_doBuild, METH_VARARGS|METH_KEYWORDS, NULL },
249 PyTypeObject spec_Type = {
250 PyVarObject_HEAD_INIT(&PyType_Type, 0)
251 "rpm.spec", /*tp_name*/
252 sizeof(specObject), /*tp_basicsize*/
254 (destructor) spec_dealloc, /*tp_dealloc*/
261 0, /*tp_as_sequence*/
269 Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
270 spec_doc, /* tp_doc */
273 0, /* tp_richcompare */
274 0, /* tp_weaklistoffset */
277 spec_methods, /* tp_methods */
279 spec_getseters, /* tp_getset */
282 0, /* tp_descr_get */
283 0, /* tp_descr_set */
284 0, /* tp_dictoffset */
287 spec_new, /* tp_new */
293 spec_Wrap(PyTypeObject *subtype, rpmSpec spec)
295 specObject * s = (specObject *)subtype->tp_alloc(subtype, 0);
296 if (s == NULL) return NULL;
299 return (PyObject *) s;
302 PyObject * specPkg_Wrap(PyTypeObject *subtype, Package pkg)
304 specPkgObject * s = (specPkgObject *)subtype->tp_alloc(subtype, 0);
305 if (s == NULL) return NULL;
308 return (PyObject *) s;