1850a50eefed1130c121f4a7289bc37f1296bd57
[platform/upstream/rpm.git] / python / spec-py.c
1 #include "rpmsystem-py.h"
2
3 #include "header-py.h"
4 #include "spec-py.h"
5
6 /** \ingroup python
7  * \name Class: Rpmspec
8  * \class Rpmspec
9  * \brief A python rpm.spec object represents an RPM spec file set.
10  * 
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.
16  *  
17  *  The rpm.spec object represents a parsed specfile to aid extraction of data.
18  *  
19  *  For example
20  * \code
21  *  import rpm
22  *  rpm.addMacro("_topdir","/path/to/topdir")
23  *  s=rpm.spec("foo.spec")
24  *  print s.prep()
25  * \endcode
26  *
27  *  Macros set using add macro will be used allowing testing of conditional builds
28  *
29  */
30
31 /* Header objects are in another module, some hoop jumping required... */
32 static PyObject *makeHeader(Header h)
33 {
34     PyObject *rpmmod = PyImport_ImportModuleNoBlock("rpm");
35     if (rpmmod == NULL) return NULL;
36
37     PyObject *ptr = CAPSULE_BUILD(h, "rpm._C_Header");
38     PyObject *hdr = PyObject_CallMethod(rpmmod, "hdr", "(O)", ptr);
39     Py_XDECREF(ptr);
40     Py_XDECREF(rpmmod);
41     return hdr;
42 }
43
44 struct specPkgObject_s {
45     PyObject_HEAD
46     /*type specific fields */
47     rpmSpecPkg pkg;
48 };
49
50 static char specPkg_doc[] =
51 "";
52
53 static PyObject * specpkg_get_header(specPkgObject *s, void *closure)
54 {
55     return makeHeader(rpmSpecPkgHeader(s->pkg));
56 }
57
58 static PyGetSetDef specpkg_getseters[] = {
59     { "header", (getter) specpkg_get_header, NULL, NULL },
60     { NULL }    /* sentinel */
61 };
62
63 PyTypeObject specPkg_Type = {
64         PyVarObject_HEAD_INIT(&PyType_Type, 0)
65         "rpm.specpkg",                  /* tp_name */
66         sizeof(specPkgObject),          /* tp_size */
67         0,                              /* tp_itemsize */
68         0,                              /* tp_dealloc */
69         0,                              /* tp_print */
70         0,                              /* tp_getattr */
71         0,                              /* tp_setattr */
72         0,                              /* tp_compare */
73         0,                              /* tp_repr */
74         0,                              /* tp_as_number */
75         0,                              /* tp_as_sequence */
76         0,                              /* tp_as_mapping */
77         0,                              /* tp_hash */
78         0,                              /* tp_call */
79         0,                              /* tp_str */
80         PyObject_GenericGetAttr,        /* tp_getattro */
81         PyObject_GenericSetAttr,        /* tp_setattro */
82         0,                              /* tp_as_buffer */
83         Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */
84         specPkg_doc,                    /* tp_doc */
85         0,                              /* tp_traverse */
86         0,                              /* tp_clear */
87         0,                              /* tp_richcompare */
88         0,                              /* tp_weaklistoffset */
89         0,                              /* tp_iter */
90         0,                              /* tp_iternext */
91         0,                              /* tp_methods */
92         0,                              /* tp_members */
93         specpkg_getseters,              /* tp_getset */
94         0,                              /* tp_base */
95         0,                              /* tp_dict */
96         0,                              /* tp_descr_get */
97         0,                              /* tp_descr_set */
98         0,                              /* tp_dictoffset */
99         0,                              /* tp_init */
100         0,                              /* tp_alloc */
101         0,                              /* tp_new */
102         0,                              /* tp_free */
103         0,                              /* tp_is_gc */
104 };
105
106 struct specObject_s {
107     PyObject_HEAD
108     /*type specific fields */
109     rpmSpec spec;
110 };
111
112 static void 
113 spec_dealloc(specObject * s) 
114 {
115     if (s->spec) {
116         s->spec=rpmSpecFree(s->spec);
117     }
118     Py_TYPE(s)->tp_free((PyObject *)s);
119 }
120
121 static PyObject * getSection(rpmSpec spec, int section)
122 {
123     const char *sect = rpmSpecGetSection(spec, section);
124     if (sect) {
125         return Py_BuildValue("s", sect);
126     }
127     Py_RETURN_NONE;
128 }
129
130 static PyObject * 
131 spec_get_prep(specObject * s, void *closure) 
132 {
133     return getSection(s->spec, RPMBUILD_PREP);
134 }
135
136 static PyObject * 
137 spec_get_build(specObject * s, void *closure) 
138 {
139     return getSection(s->spec, RPMBUILD_BUILD);
140 }
141
142 static PyObject * spec_get_install(specObject * s, void *closure) 
143 {
144     return getSection(s->spec, RPMBUILD_INSTALL);
145 }
146
147 static PyObject * spec_get_clean(specObject * s, void *closure) 
148 {
149     return getSection(s->spec, RPMBUILD_CLEAN);
150 }
151
152 static PyObject * spec_get_sources(specObject *s, void *closure)
153 {
154     PyObject *sourceList;
155     rpmSpecSrc source;
156
157     sourceList = PyList_New(0);
158     if (!sourceList) {
159         return NULL;
160     }
161
162     rpmSpecSrcIter iter = rpmSpecSrcIterInit(s->spec);
163     while ((source = rpmSpecSrcIterNext(iter)) != NULL) {
164         PyObject *srcUrl = Py_BuildValue("(sii)",
165                                 rpmSpecSrcFilename(source, 1),
166                                 rpmSpecSrcNum(source),
167                                 rpmSpecSrcFlags(source)); 
168         if (!srcUrl) {
169             Py_DECREF(sourceList);
170             return NULL;
171         }
172         PyList_Append(sourceList, srcUrl);
173         Py_DECREF(srcUrl);
174     } 
175     rpmSpecSrcIterFree(iter);
176
177     return sourceList;
178
179 }
180
181 static PyObject * spec_get_packages(specObject *s, void *closure)
182 {
183     rpmSpecPkg pkg;
184     PyObject *pkgList;
185     rpmSpecPkgIter iter;
186
187     pkgList = PyList_New(0);
188     if (!pkgList) {
189         return NULL;
190     }
191
192     iter = rpmSpecPkgIterInit(s->spec);
193
194     while ((pkg = rpmSpecPkgIterNext(iter)) != NULL) {
195         PyObject *po = specPkg_Wrap(&specPkg_Type, pkg);
196         if (!po) {
197             rpmSpecPkgIterFree(iter);
198             Py_DECREF(pkgList);
199             return NULL;
200         }
201         PyList_Append(pkgList, po);
202         Py_DECREF(po);
203     }
204     rpmSpecPkgIterFree(iter);
205     return pkgList;
206 }
207
208 static PyObject * spec_get_source_header(specObject *s, void *closure)
209 {
210     return makeHeader(rpmSpecSourceHeader(s->spec));
211 }
212
213 static char spec_doc[] = "RPM Spec file object";
214
215 static PyGetSetDef spec_getseters[] = {
216     {"sources",   (getter) spec_get_sources, NULL, NULL },
217     {"prep",   (getter) spec_get_prep, NULL, NULL },
218     {"build",   (getter) spec_get_build, NULL, NULL },
219     {"install",   (getter) spec_get_install, NULL, NULL },
220     {"clean",   (getter) spec_get_clean, NULL, NULL },
221     {"packages", (getter) spec_get_packages, NULL, NULL },
222     {"sourceHeader", (getter) spec_get_source_header, NULL, NULL },
223     {NULL}  /* Sentinel */
224 };
225
226 static PyObject *spec_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
227 {
228     char * kwlist[] = {"specfile", "flags", NULL};
229     const char * specfile;
230     rpmSpec spec = NULL;
231     /* XXX This is a dumb default but anything else breaks compatibility... */
232     rpmSpecFlags flags = (RPMSPEC_ANYARCH|RPMSPEC_FORCE);
233
234     if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|i:spec_new", kwlist,
235                                      &specfile, &flags))
236         return NULL;
237
238     spec = rpmSpecParse(specfile, flags, NULL);
239     if (spec == NULL) {
240         PyErr_SetString(PyExc_ValueError, "can't parse specfile\n");
241         return NULL;
242     }
243
244     return spec_Wrap(subtype, spec);
245 }
246
247 static PyObject * spec_doBuild(specObject *self, PyObject *args, PyObject *kwds)
248 {
249     char * kwlist[] = { "buildAmount", "pkgFlags", NULL };
250     struct rpmBuildArguments_s ba = { 0 };
251
252     if (!PyArg_ParseTupleAndKeywords(args, kwds, "i|i:spec_doBuild",
253                         kwlist, &ba.buildAmount, &ba.pkgFlags))
254         return NULL;
255
256     return PyBool_FromLong(rpmSpecBuild(self->spec, &ba) == RPMRC_OK);
257 }
258
259 static struct PyMethodDef spec_methods[] = {
260     { "_doBuild", (PyCFunction)spec_doBuild, METH_VARARGS|METH_KEYWORDS, NULL },
261     { NULL, NULL }
262 };
263
264 PyTypeObject spec_Type = {
265     PyVarObject_HEAD_INIT(&PyType_Type, 0)
266     "rpm.spec",               /*tp_name*/
267     sizeof(specObject),        /*tp_basicsize*/
268     0,                         /*tp_itemsize*/
269     (destructor) spec_dealloc, /*tp_dealloc*/
270     0,                         /*tp_print*/
271     0,                         /*tp_getattr*/
272     0,                         /*tp_setattr*/
273     0,                         /*tp_compare*/
274     0,                         /*tp_repr*/
275     0,                         /*tp_as_number*/
276     0,                         /*tp_as_sequence*/
277     0,                         /*tp_as_mapping*/
278     0,                         /*tp_hash */
279     0,                         /*tp_call*/
280     0,                         /*tp_str*/
281     0,                         /*tp_getattro*/
282     0,                         /*tp_setattro*/
283     0,                         /*tp_as_buffer*/
284     Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
285     spec_doc,                  /* tp_doc */
286     0,                         /* tp_traverse */
287     0,                         /* tp_clear */
288     0,                         /* tp_richcompare */
289     0,                         /* tp_weaklistoffset */
290     0,                         /* tp_iter */
291     0,                         /* tp_iternext */
292     spec_methods,              /* tp_methods */
293     0,                         /* tp_members */
294     spec_getseters,            /* tp_getset */
295     0,                         /* tp_base */
296     0,                         /* tp_dict */
297     0,                         /* tp_descr_get */
298     0,                         /* tp_descr_set */
299     0,                         /* tp_dictoffset */
300     0,                         /* tp_init */
301     0,                         /* tp_alloc */
302     spec_new,                  /* tp_new */
303     0,                         /* tp_free */
304     0,                         /* tp_is_gc */
305 };
306
307 PyObject *
308 spec_Wrap(PyTypeObject *subtype, rpmSpec spec) 
309 {
310     specObject * s = (specObject *)subtype->tp_alloc(subtype, 0);
311     if (s == NULL) return NULL;
312
313     s->spec = spec; 
314     return (PyObject *) s;
315 }
316
317 PyObject * specPkg_Wrap(PyTypeObject *subtype, rpmSpecPkg pkg) 
318 {
319     specPkgObject * s = (specPkgObject *)subtype->tp_alloc(subtype, 0);
320     if (s == NULL) return NULL;
321
322     s->pkg = pkg;
323     return (PyObject *) s;
324 }
325