Call (sub)type tp_free from destructors
[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 struct specObject_s {
32     PyObject_HEAD
33     /*type specific fields */
34     rpmSpec spec;
35 };
36
37 static void 
38 spec_dealloc(specObject * s) 
39 {
40     if (s->spec) {
41         s->spec=freeSpec(s->spec);
42     }
43     s->ob_type->tp_free((PyObject *)s);
44 }
45
46 /* XXX TODO return something sensible if spec exists but component (eg %clean)
47  * does not. Possibly "" or None */
48
49 static PyObject * 
50 spec_get_buildroot(specObject * s) 
51 {
52     rpmSpec spec = specFromSpec(s);
53     if (spec != NULL && spec->buildRoot) {
54         return Py_BuildValue("s", spec->buildRoot);
55     }
56     else {
57         return NULL;
58     }
59 }
60
61 static PyObject * 
62 spec_get_prep(specObject * s) 
63 {
64     rpmSpec spec = specFromSpec(s);
65     PyObject *res = NULL;
66     if (spec != NULL && spec->prep) {
67         res = Py_BuildValue("s",getStringBuf(spec->prep));
68     }
69     return res;
70 }
71
72 static PyObject * 
73 spec_get_build(specObject * s) 
74 {
75     rpmSpec spec = specFromSpec(s);
76     PyObject *res = NULL;
77     if (spec != NULL && spec->build) {
78         res = Py_BuildValue("s",getStringBuf(spec->build));
79     }
80     return res;
81 }
82
83 static PyObject * 
84 spec_get_install(specObject * s) 
85 {
86     rpmSpec spec = specFromSpec(s);
87     PyObject *res = NULL;
88     if (spec != NULL && spec->install) {
89         res = Py_BuildValue("s",getStringBuf(spec->install));
90     }
91     return res;
92 }
93
94 static PyObject * 
95 spec_get_clean(specObject * s) 
96 {
97     rpmSpec spec = specFromSpec(s);
98     PyObject *res = NULL;
99     if (spec != NULL && spec->clean) {
100         res = Py_BuildValue("s",getStringBuf(spec->clean));
101     }
102     return res;
103 }
104
105 static PyObject *
106 spec_get_sources(specObject *s)
107 {
108     struct Source * source;
109     PyObject *sourceList, *srcUrl;
110     rpmSpec spec;
111     char * fullSource;
112
113     sourceList = PyList_New(0);
114     spec = specFromSpec(s);
115     if ( spec != NULL) {
116         source = spec->sources;
117
118          while (source != NULL) {
119             fullSource = source->fullSource;
120             srcUrl = Py_BuildValue("(sii)", fullSource, source->num, source->flags);
121             PyList_Append(sourceList, srcUrl);
122             source=source->next;
123         } 
124
125         return PyList_AsTuple(sourceList);
126     }
127     else {
128         return NULL;
129     }
130
131 }
132
133 static char spec_doc[] = "RPM Spec file object";
134
135 static PyMethodDef spec_Spec_methods[] = {
136     {"sources",   (PyCFunction) spec_get_sources, METH_VARARGS,  NULL },
137     {"prep",   (PyCFunction) spec_get_prep, METH_VARARGS,  NULL },
138     {"build",   (PyCFunction) spec_get_build, METH_VARARGS,  NULL },
139     {"install",   (PyCFunction) spec_get_install, METH_VARARGS,  NULL },
140     {"clean",   (PyCFunction) spec_get_clean, METH_VARARGS,  NULL },
141     {"buildRoot",   (PyCFunction) spec_get_buildroot, METH_VARARGS,  NULL },
142     {NULL}  /* Sentinel */
143 };
144
145 static PyObject *spec_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
146 {
147     rpmts ts = NULL;
148     const char * specfile;
149     rpmSpec spec = NULL;
150     char * buildRoot = NULL;
151     int recursing = 0;
152     char * passPhrase = "";
153     char *cookie = NULL;
154     int anyarch = 1;
155     int force = 1;
156     char * kwlist[] = {"specfile", NULL};
157
158     if (!PyArg_ParseTupleAndKeywords(args, kwds, "s:spec_new", kwlist,
159                                      &specfile))
160         return NULL;
161
162     /*
163      * Just how hysterical can you get? We need to create a transaction
164      * set to get back the results from parseSpec()...
165      */
166     ts = rpmtsCreate();
167     if (parseSpec(ts, specfile,"/", buildRoot,recursing, passPhrase,
168                   cookie, anyarch, force) == 0) {
169         spec = rpmtsSpec(ts);
170     } else {
171          PyErr_SetString(pyrpmError, "can't parse specfile\n");
172     }
173     rpmtsFree(ts);
174
175     return spec ? spec_Wrap(subtype, spec) : NULL;
176 }
177
178 PyTypeObject spec_Type = {
179     PyObject_HEAD_INIT(&PyType_Type)
180     0,                         /*ob_size*/
181     "rpm.spec",               /*tp_name*/
182     sizeof(specObject),        /*tp_basicsize*/
183     0,                         /*tp_itemsize*/
184     (destructor) spec_dealloc, /*tp_dealloc*/
185     0,                         /*tp_print*/
186     0,                         /*tp_getattr*/
187     0,                         /*tp_setattr*/
188     0,                         /*tp_compare*/
189     0,                         /*tp_repr*/
190     0,                         /*tp_as_number*/
191     0,                         /*tp_as_sequence*/
192     0,                         /*tp_as_mapping*/
193     0,                         /*tp_hash */
194     0,                         /*tp_call*/
195     0,                         /*tp_str*/
196     0,                         /*tp_getattro*/
197     0,                         /*tp_setattro*/
198     0,                         /*tp_as_buffer*/
199     Py_TPFLAGS_DEFAULT,        /*tp_flags*/
200     spec_doc,                  /* tp_doc */
201     0,                         /* tp_traverse */
202     0,                         /* tp_clear */
203     0,                         /* tp_richcompare */
204     0,                         /* tp_weaklistoffset */
205     0,                         /* tp_iter */
206     0,                         /* tp_iternext */
207     spec_Spec_methods,         /* tp_methods */
208     0,                         /* tp_members */
209     0,                         /* tp_getset */
210     0,                         /* tp_base */
211     0,                         /* tp_dict */
212     0,                         /* tp_descr_get */
213     0,                         /* tp_descr_set */
214     0,                         /* tp_dictoffset */
215     0,                         /* tp_init */
216     0,                         /* tp_alloc */
217     spec_new,                  /* tp_new */
218     0,                         /* tp_free */
219     0,                         /* tp_is_gc */
220 };
221
222 rpmSpec specFromSpec(specObject *s) 
223 {
224     return s->spec;
225 }
226
227 PyObject *
228 spec_Wrap(PyTypeObject *subtype, rpmSpec spec) 
229 {
230     specObject * s = (specObject *)subtype->tp_alloc(subtype, 0);
231     if (s == NULL) return PyErr_NoMemory();
232
233     s->spec = spec; 
234     return (PyObject *) s;
235 }