upgrade rpm version to 4.14.1
[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.rpmPushMacro("_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     specObject *source_spec;
49 };
50
51 static void specPkg_dealloc(specPkgObject * s)
52 {
53     Py_DECREF(s->source_spec);
54 }
55
56 static PyObject *pkgGetSection(rpmSpecPkg pkg, int section)
57 {
58     char *sect = rpmSpecPkgGetSection(pkg, section);
59     if (sect != NULL) {
60         PyObject *ps = PyBytes_FromString(sect);
61         free(sect);
62         if (ps != NULL)
63             return ps;
64     }
65     Py_RETURN_NONE;
66 }
67
68 static char specPkg_doc[] =
69 "Package data parsed from spec file.";
70
71 static PyObject * specpkg_get_header(specPkgObject *s, void *closure)
72 {
73     return makeHeader(rpmSpecPkgHeader(s->pkg));
74 }
75
76 static PyObject * specpkg_get_fileFile(specPkgObject *s, void *closure)
77 {
78     return  pkgGetSection(s->pkg, RPMBUILD_FILE_FILE);
79 }
80
81 static PyObject * specpkg_get_fileList(specPkgObject *s, void *closure)
82 {
83     return  pkgGetSection(s->pkg, RPMBUILD_FILE_LIST);
84 }
85
86 static PyObject * specpkg_get_policyList(specPkgObject *s, void *closure)
87 {
88     return  pkgGetSection(s->pkg, RPMBUILD_POLICY);
89 }
90
91 static PyGetSetDef specpkg_getseters[] = {
92     { "header",     (getter) specpkg_get_header,     NULL, NULL },
93     { "fileFile",   (getter) specpkg_get_fileFile,   NULL, NULL },
94     { "fileList",   (getter) specpkg_get_fileList,   NULL, NULL },
95     { "policyList", (getter) specpkg_get_policyList, NULL, NULL },
96     { NULL }   /* sentinel */
97 };
98
99 PyTypeObject specPkg_Type = {
100         PyVarObject_HEAD_INIT(&PyType_Type, 0)
101         "rpm.specpkg",                  /* tp_name */
102         sizeof(specPkgObject),          /* tp_size */
103         0,                              /* tp_itemsize */
104         (destructor) specPkg_dealloc,   /* tp_dealloc */
105         0,                              /* tp_print */
106         0,                              /* tp_getattr */
107         0,                              /* tp_setattr */
108         0,                              /* tp_compare */
109         0,                              /* tp_repr */
110         0,                              /* tp_as_number */
111         0,                              /* tp_as_sequence */
112         0,                              /* tp_as_mapping */
113         0,                              /* tp_hash */
114         0,                              /* tp_call */
115         0,                              /* tp_str */
116         PyObject_GenericGetAttr,        /* tp_getattro */
117         PyObject_GenericSetAttr,        /* tp_setattro */
118         0,                              /* tp_as_buffer */
119         Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */
120         specPkg_doc,                    /* tp_doc */
121         0,                              /* tp_traverse */
122         0,                              /* tp_clear */
123         0,                              /* tp_richcompare */
124         0,                              /* tp_weaklistoffset */
125         0,                              /* tp_iter */
126         0,                              /* tp_iternext */
127         0,                              /* tp_methods */
128         0,                              /* tp_members */
129         specpkg_getseters,              /* tp_getset */
130         0,                              /* tp_base */
131         0,                              /* tp_dict */
132         0,                              /* tp_descr_get */
133         0,                              /* tp_descr_set */
134         0,                              /* tp_dictoffset */
135         0,                              /* tp_init */
136         0,                              /* tp_alloc */
137         0,                              /* tp_new */
138         0,                              /* tp_free */
139         0,                              /* tp_is_gc */
140 };
141
142 struct specObject_s {
143     PyObject_HEAD
144     /*type specific fields */
145     rpmSpec spec;
146 };
147
148 static void 
149 spec_dealloc(specObject * s) 
150 {
151     if (s->spec) {
152         s->spec=rpmSpecFree(s->spec);
153     }
154     Py_TYPE(s)->tp_free((PyObject *)s);
155 }
156
157 static PyObject * getSection(rpmSpec spec, int section)
158 {
159     const char *sect = rpmSpecGetSection(spec, section);
160     if (sect) {
161         return Py_BuildValue("s", sect);
162     }
163     Py_RETURN_NONE;
164 }
165
166 static PyObject *
167 spec_get_parsed(specObject * s, void *closure)
168 {
169     return getSection(s->spec, RPMBUILD_NONE);
170 }
171
172 static PyObject * 
173 spec_get_prep(specObject * s, void *closure) 
174 {
175     return getSection(s->spec, RPMBUILD_PREP);
176 }
177
178 static PyObject * 
179 spec_get_build(specObject * s, void *closure) 
180 {
181     return getSection(s->spec, RPMBUILD_BUILD);
182 }
183
184 static PyObject * spec_get_install(specObject * s, void *closure) 
185 {
186     return getSection(s->spec, RPMBUILD_INSTALL);
187 }
188
189 static PyObject * spec_get_check(specObject * s, void *closure)
190 {
191     return getSection(s->spec, RPMBUILD_CHECK);
192 }
193
194 static PyObject * spec_get_clean(specObject * s, void *closure) 
195 {
196     return getSection(s->spec, RPMBUILD_CLEAN);
197 }
198
199 static PyObject * spec_get_sources(specObject *s, void *closure)
200 {
201     PyObject *sourceList;
202     rpmSpecSrc source;
203
204     sourceList = PyList_New(0);
205     if (!sourceList) {
206         return NULL;
207     }
208
209     rpmSpecSrcIter iter = rpmSpecSrcIterInit(s->spec);
210     while ((source = rpmSpecSrcIterNext(iter)) != NULL) {
211         PyObject *srcUrl = Py_BuildValue("(sii)",
212                                 rpmSpecSrcFilename(source, 1),
213                                 rpmSpecSrcNum(source),
214                                 rpmSpecSrcFlags(source)); 
215         if (!srcUrl) {
216             Py_DECREF(sourceList);
217             return NULL;
218         }
219         PyList_Append(sourceList, srcUrl);
220         Py_DECREF(srcUrl);
221     } 
222     rpmSpecSrcIterFree(iter);
223
224     return sourceList;
225
226 }
227
228 static PyObject * spec_get_packages(specObject *s, void *closure)
229 {
230     rpmSpecPkg pkg;
231     PyObject *pkgList;
232     rpmSpecPkgIter iter;
233
234     pkgList = PyList_New(0);
235     if (!pkgList) {
236         return NULL;
237     }
238
239     iter = rpmSpecPkgIterInit(s->spec);
240
241     while ((pkg = rpmSpecPkgIterNext(iter)) != NULL) {
242         PyObject *po = specPkg_Wrap(&specPkg_Type, pkg, s);
243         if (!po) {
244             rpmSpecPkgIterFree(iter);
245             Py_DECREF(pkgList);
246             return NULL;
247         }
248         PyList_Append(pkgList, po);
249         Py_DECREF(po);
250     }
251     rpmSpecPkgIterFree(iter);
252     return pkgList;
253 }
254
255 static PyObject * spec_get_source_header(specObject *s, void *closure)
256 {
257     return makeHeader(rpmSpecSourceHeader(s->spec));
258 }
259
260 static char spec_doc[] = "RPM Spec file object";
261
262 static PyGetSetDef spec_getseters[] = {
263     {"sources",   (getter) spec_get_sources, NULL, NULL },
264     {"parsed",    (getter) spec_get_parsed, NULL, NULL},
265     {"prep",   (getter) spec_get_prep, NULL, NULL },
266     {"build",   (getter) spec_get_build, NULL, NULL },
267     {"install",   (getter) spec_get_install, NULL, NULL },
268     {"check",   (getter) spec_get_check, NULL, NULL },
269     {"clean",   (getter) spec_get_clean, NULL, NULL },
270     {"packages", (getter) spec_get_packages, NULL, NULL },
271     {"sourceHeader", (getter) spec_get_source_header, NULL, NULL },
272     {NULL}  /* Sentinel */
273 };
274
275 static PyObject *spec_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
276 {
277     char * kwlist[] = {"specfile", "flags", NULL};
278     const char * specfile;
279     rpmSpec spec = NULL;
280     /* XXX This is a dumb default but anything else breaks compatibility... */
281     rpmSpecFlags flags = (RPMSPEC_ANYARCH|RPMSPEC_FORCE);
282
283     if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|i:spec_new", kwlist,
284                                      &specfile, &flags))
285         return NULL;
286
287     spec = rpmSpecParse(specfile, flags, NULL);
288     if (spec == NULL) {
289         PyErr_SetString(PyExc_ValueError, "can't parse specfile\n");
290         return NULL;
291     }
292
293     return spec_Wrap(subtype, spec);
294 }
295
296 static PyObject * spec_doBuild(specObject *self, PyObject *args, PyObject *kwds)
297 {
298     char * kwlist[] = { "buildAmount", "pkgFlags", NULL };
299     struct rpmBuildArguments_s ba = { 0 };
300
301     if (!PyArg_ParseTupleAndKeywords(args, kwds, "i|i:spec_doBuild",
302                         kwlist, &ba.buildAmount, &ba.pkgFlags))
303         return NULL;
304
305     return PyBool_FromLong(rpmSpecBuild(self->spec, &ba) == RPMRC_OK);
306 }
307
308 static struct PyMethodDef spec_methods[] = {
309     { "_doBuild", (PyCFunction)spec_doBuild, METH_VARARGS|METH_KEYWORDS, NULL },
310     { NULL, NULL }
311 };
312
313 PyTypeObject spec_Type = {
314     PyVarObject_HEAD_INIT(&PyType_Type, 0)
315     "rpm.spec",               /*tp_name*/
316     sizeof(specObject),        /*tp_basicsize*/
317     0,                         /*tp_itemsize*/
318     (destructor) spec_dealloc, /*tp_dealloc*/
319     0,                         /*tp_print*/
320     0,                         /*tp_getattr*/
321     0,                         /*tp_setattr*/
322     0,                         /*tp_compare*/
323     0,                         /*tp_repr*/
324     0,                         /*tp_as_number*/
325     0,                         /*tp_as_sequence*/
326     0,                         /*tp_as_mapping*/
327     0,                         /*tp_hash */
328     0,                         /*tp_call*/
329     0,                         /*tp_str*/
330     0,                         /*tp_getattro*/
331     0,                         /*tp_setattro*/
332     0,                         /*tp_as_buffer*/
333     Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
334     spec_doc,                  /* tp_doc */
335     0,                         /* tp_traverse */
336     0,                         /* tp_clear */
337     0,                         /* tp_richcompare */
338     0,                         /* tp_weaklistoffset */
339     0,                         /* tp_iter */
340     0,                         /* tp_iternext */
341     spec_methods,              /* tp_methods */
342     0,                         /* tp_members */
343     spec_getseters,            /* tp_getset */
344     0,                         /* tp_base */
345     0,                         /* tp_dict */
346     0,                         /* tp_descr_get */
347     0,                         /* tp_descr_set */
348     0,                         /* tp_dictoffset */
349     0,                         /* tp_init */
350     0,                         /* tp_alloc */
351     spec_new,                  /* tp_new */
352     0,                         /* tp_free */
353     0,                         /* tp_is_gc */
354 };
355
356 PyObject *
357 spec_Wrap(PyTypeObject *subtype, rpmSpec spec) 
358 {
359     specObject * s = (specObject *)subtype->tp_alloc(subtype, 0);
360     if (s == NULL) return NULL;
361
362     s->spec = spec; 
363     return (PyObject *) s;
364 }
365
366 PyObject * specPkg_Wrap(PyTypeObject *subtype, rpmSpecPkg pkg, specObject *source)
367 {
368     specPkgObject * s = (specPkgObject *)subtype->tp_alloc(subtype, 0);
369     if (s == NULL) return NULL;
370
371     s->pkg = pkg;
372     s->source_spec = source;
373     Py_INCREF(s->source_spec);
374     return (PyObject *) s;
375 }
376