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