1 #include "rpmsystem-py.h"
9 * \brief A python rpm.spec object represents an RPM spec file set.
11 * The spec file is at the heart of RPM's packaging building process. Similar
12 * in concept to a makefile, it contains information required by RPM to build
13 * the package, as well as instructions telling RPM how to build it. The spec
14 * file also dictates exactly what files are a part of the package, and where
15 * they should be installed.
17 * The rpm.spec object represents a parsed specfile to aid extraction of data.
22 * rpm.addMacro("_topdir","/path/to/topdir")
23 * s=rpm.spec("foo.spec")
27 * Macros set using add macro will be used allowing testing of conditional builds
31 /* Header objects are in another module, some hoop jumping required... */
32 static PyObject *makeHeader(Header h)
34 PyObject *rpmmod = PyImport_ImportModuleNoBlock("rpm");
35 if (rpmmod == NULL) return NULL;
37 PyObject *ptr = CAPSULE_BUILD(h, "rpm._C_Header");
38 PyObject *hdr = PyObject_CallMethod(rpmmod, "hdr", "(O)", ptr);
44 struct specPkgObject_s {
46 /*type specific fields */
50 static char specPkg_doc[] =
53 static PyObject * specpkg_get_header(specPkgObject *s, void *closure)
55 return makeHeader(rpmSpecPkgHeader(s->pkg));
58 static PyGetSetDef specpkg_getseters[] = {
59 { "header", (getter) specpkg_get_header, NULL, NULL },
60 { NULL } /* sentinel */
63 PyTypeObject specPkg_Type = {
64 PyVarObject_HEAD_INIT(&PyType_Type, 0)
65 "rpm.specpkg", /* tp_name */
66 sizeof(specPkgObject), /* tp_size */
75 0, /* tp_as_sequence */
76 0, /* tp_as_mapping */
80 PyObject_GenericGetAttr, /* tp_getattro */
81 PyObject_GenericSetAttr, /* tp_setattro */
83 Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */
84 specPkg_doc, /* tp_doc */
87 0, /* tp_richcompare */
88 0, /* tp_weaklistoffset */
93 specpkg_getseters, /* tp_getset */
98 0, /* tp_dictoffset */
106 struct specObject_s {
108 /*type specific fields */
113 spec_dealloc(specObject * s)
116 s->spec=rpmSpecFree(s->spec);
118 Py_TYPE(s)->tp_free((PyObject *)s);
121 static PyObject * getSection(rpmSpec spec, int section)
123 const char *sect = rpmSpecGetSection(spec, section);
125 return Py_BuildValue("s", sect);
131 spec_get_prep(specObject * s, void *closure)
133 return getSection(s->spec, RPMBUILD_PREP);
137 spec_get_build(specObject * s, void *closure)
139 return getSection(s->spec, RPMBUILD_BUILD);
142 static PyObject * spec_get_install(specObject * s, void *closure)
144 return getSection(s->spec, RPMBUILD_INSTALL);
147 static PyObject * spec_get_clean(specObject * s, void *closure)
149 return getSection(s->spec, RPMBUILD_CLEAN);
152 static PyObject * spec_get_sources(specObject *s, void *closure)
154 PyObject *sourceList = PyList_New(0);
157 rpmSpecSrcIter iter = rpmSpecSrcIterInit(s->spec);
158 while ((source = rpmSpecSrcIterNext(iter)) != NULL) {
159 PyObject *srcUrl = Py_BuildValue("(sii)",
160 rpmSpecSrcFilename(source, 1),
161 rpmSpecSrcNum(source),
162 rpmSpecSrcFlags(source));
163 PyList_Append(sourceList, srcUrl);
166 rpmSpecSrcIterFree(iter);
172 static PyObject * spec_get_packages(specObject *s, void *closure)
175 PyObject *pkgList = PyList_New(0);
176 rpmSpecPkgIter iter = rpmSpecPkgIterInit(s->spec);
178 while ((pkg = rpmSpecPkgIterNext(iter)) != NULL) {
179 PyObject *po = specPkg_Wrap(&specPkg_Type, pkg);
180 PyList_Append(pkgList, po);
183 rpmSpecPkgIterFree(iter);
187 static PyObject * spec_get_source_header(specObject *s, void *closure)
189 return makeHeader(rpmSpecSourceHeader(s->spec));
192 static char spec_doc[] = "RPM Spec file object";
194 static PyGetSetDef spec_getseters[] = {
195 {"sources", (getter) spec_get_sources, NULL, NULL },
196 {"prep", (getter) spec_get_prep, NULL, NULL },
197 {"build", (getter) spec_get_build, NULL, NULL },
198 {"install", (getter) spec_get_install, NULL, NULL },
199 {"clean", (getter) spec_get_clean, NULL, NULL },
200 {"packages", (getter) spec_get_packages, NULL, NULL },
201 {"sourceHeader", (getter) spec_get_source_header, NULL, NULL },
202 {NULL} /* Sentinel */
205 static PyObject *spec_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
207 char * kwlist[] = {"specfile", "flags", NULL};
208 const char * specfile;
210 /* XXX This is a dumb default but anything else breaks compatibility... */
211 rpmSpecFlags flags = (RPMSPEC_ANYARCH|RPMSPEC_FORCE);
213 if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|i:spec_new", kwlist,
217 spec = rpmSpecParse(specfile, flags, NULL);
219 PyErr_SetString(PyExc_ValueError, "can't parse specfile\n");
223 return spec_Wrap(subtype, spec);
226 static PyObject * spec_doBuild(specObject *self, PyObject *args, PyObject *kwds)
228 char * kwlist[] = { "buildAmount", "pkgFlags", NULL };
229 struct rpmBuildArguments_s ba = { 0 };
231 if (!PyArg_ParseTupleAndKeywords(args, kwds, "i|i:spec_doBuild",
232 kwlist, &ba.buildAmount, &ba.pkgFlags))
235 return PyBool_FromLong(rpmSpecBuild(self->spec, &ba) == RPMRC_OK);
238 static struct PyMethodDef spec_methods[] = {
239 { "_doBuild", (PyCFunction)spec_doBuild, METH_VARARGS|METH_KEYWORDS, NULL },
243 PyTypeObject spec_Type = {
244 PyVarObject_HEAD_INIT(&PyType_Type, 0)
245 "rpm.spec", /*tp_name*/
246 sizeof(specObject), /*tp_basicsize*/
248 (destructor) spec_dealloc, /*tp_dealloc*/
255 0, /*tp_as_sequence*/
263 Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
264 spec_doc, /* tp_doc */
267 0, /* tp_richcompare */
268 0, /* tp_weaklistoffset */
271 spec_methods, /* tp_methods */
273 spec_getseters, /* tp_getset */
276 0, /* tp_descr_get */
277 0, /* tp_descr_set */
278 0, /* tp_dictoffset */
281 spec_new, /* tp_new */
287 spec_Wrap(PyTypeObject *subtype, rpmSpec spec)
289 specObject * s = (specObject *)subtype->tp_alloc(subtype, 0);
290 if (s == NULL) return NULL;
293 return (PyObject *) s;
296 PyObject * specPkg_Wrap(PyTypeObject *subtype, rpmSpecPkg pkg)
298 specPkgObject * s = (specPkgObject *)subtype->tp_alloc(subtype, 0);
299 if (s == NULL) return NULL;
302 return (PyObject *) s;