49b9e1d1a9b0f1817f14130481ddb65836961e7b
[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 = PyList_New(0);
155     rpmSpecSrc source;
156
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);
164         Py_DECREF(srcUrl);
165     } 
166     rpmSpecSrcIterFree(iter);
167
168     return sourceList;
169
170 }
171
172 static PyObject * spec_get_packages(specObject *s, void *closure)
173 {
174     rpmSpecPkg pkg;
175     PyObject *pkgList = PyList_New(0);
176     rpmSpecPkgIter iter = rpmSpecPkgIterInit(s->spec);
177
178     while ((pkg = rpmSpecPkgIterNext(iter)) != NULL) {
179         PyObject *po = specPkg_Wrap(&specPkg_Type, pkg);
180         PyList_Append(pkgList, po);
181         Py_DECREF(po);
182     }
183     rpmSpecPkgIterFree(iter);
184     return pkgList;
185 }
186
187 static PyObject * spec_get_source_header(specObject *s, void *closure)
188 {
189     return makeHeader(rpmSpecSourceHeader(s->spec));
190 }
191
192 static char spec_doc[] = "RPM Spec file object";
193
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 */
203 };
204
205 static PyObject *spec_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
206 {
207     char * kwlist[] = {"specfile", "flags", NULL};
208     const char * specfile;
209     rpmSpec spec = NULL;
210     /* XXX This is a dumb default but anything else breaks compatibility... */
211     rpmSpecFlags flags = (RPMSPEC_ANYARCH|RPMSPEC_FORCE);
212
213     if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|i:spec_new", kwlist,
214                                      &specfile, &flags))
215         return NULL;
216
217     spec = rpmSpecParse(specfile, flags, NULL);
218     if (spec == NULL) {
219         PyErr_SetString(PyExc_ValueError, "can't parse specfile\n");
220         return NULL;
221     }
222
223     return spec_Wrap(subtype, spec);
224 }
225
226 static PyObject * spec_doBuild(specObject *self, PyObject *args, PyObject *kwds)
227 {
228     char * kwlist[] = { "buildAmount", "pkgFlags", NULL };
229     struct rpmBuildArguments_s ba = { 0 };
230
231     if (!PyArg_ParseTupleAndKeywords(args, kwds, "i|i:spec_doBuild",
232                         kwlist, &ba.buildAmount, &ba.pkgFlags))
233         return NULL;
234
235     return PyBool_FromLong(rpmSpecBuild(self->spec, &ba) == RPMRC_OK);
236 }
237
238 static struct PyMethodDef spec_methods[] = {
239     { "_doBuild", (PyCFunction)spec_doBuild, METH_VARARGS|METH_KEYWORDS, NULL },
240     { NULL, NULL }
241 };
242
243 PyTypeObject spec_Type = {
244     PyVarObject_HEAD_INIT(&PyType_Type, 0)
245     "rpm.spec",               /*tp_name*/
246     sizeof(specObject),        /*tp_basicsize*/
247     0,                         /*tp_itemsize*/
248     (destructor) spec_dealloc, /*tp_dealloc*/
249     0,                         /*tp_print*/
250     0,                         /*tp_getattr*/
251     0,                         /*tp_setattr*/
252     0,                         /*tp_compare*/
253     0,                         /*tp_repr*/
254     0,                         /*tp_as_number*/
255     0,                         /*tp_as_sequence*/
256     0,                         /*tp_as_mapping*/
257     0,                         /*tp_hash */
258     0,                         /*tp_call*/
259     0,                         /*tp_str*/
260     0,                         /*tp_getattro*/
261     0,                         /*tp_setattro*/
262     0,                         /*tp_as_buffer*/
263     Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
264     spec_doc,                  /* tp_doc */
265     0,                         /* tp_traverse */
266     0,                         /* tp_clear */
267     0,                         /* tp_richcompare */
268     0,                         /* tp_weaklistoffset */
269     0,                         /* tp_iter */
270     0,                         /* tp_iternext */
271     spec_methods,              /* tp_methods */
272     0,                         /* tp_members */
273     spec_getseters,            /* tp_getset */
274     0,                         /* tp_base */
275     0,                         /* tp_dict */
276     0,                         /* tp_descr_get */
277     0,                         /* tp_descr_set */
278     0,                         /* tp_dictoffset */
279     0,                         /* tp_init */
280     0,                         /* tp_alloc */
281     spec_new,                  /* tp_new */
282     0,                         /* tp_free */
283     0,                         /* tp_is_gc */
284 };
285
286 PyObject *
287 spec_Wrap(PyTypeObject *subtype, rpmSpec spec) 
288 {
289     specObject * s = (specObject *)subtype->tp_alloc(subtype, 0);
290     if (s == NULL) return NULL;
291
292     s->spec = spec; 
293     return (PyObject *) s;
294 }
295
296 PyObject * specPkg_Wrap(PyTypeObject *subtype, rpmSpecPkg pkg) 
297 {
298     specPkgObject * s = (specPkgObject *)subtype->tp_alloc(subtype, 0);
299     if (s == NULL) return NULL;
300
301     s->pkg = pkg;
302     return (PyObject *) s;
303 }
304