1 /*#############################################################################
3 # Pakfire - The IPFire package management system #
4 # Copyright (C) 2017 Pakfire development team #
6 # This program is free software: you can redistribute it and/or modify #
7 # it under the terms of the GNU General Public License as published by #
8 # the Free Software Foundation, either version 3 of the License, or #
9 # (at your option) any later version. #
11 # This program is distributed in the hope that it will be useful, #
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of #
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
14 # GNU General Public License for more details. #
16 # You should have received a copy of the GNU General Public License #
17 # along with this program. If not, see <http://www.gnu.org/licenses/>. #
19 #############################################################################*/
21 #define PY_SSIZE_T_CLEAN
25 #include <pakfire/archive.h>
26 #include <pakfire/build.h>
27 #include <pakfire/constants.h>
28 #include <pakfire/dist.h>
29 #include <pakfire/jail.h>
30 #include <pakfire/logging.h>
31 #include <pakfire/mount.h>
32 #include <pakfire/packagelist.h>
33 #include <pakfire/pakfire.h>
34 #include <pakfire/key.h>
35 #include <pakfire/repo.h>
36 #include <pakfire/repolist.h>
37 #include <pakfire/request.h>
38 #include <pakfire/util.h>
47 static PyObject
* Pakfire_new(PyTypeObject
* type
, PyObject
* args
, PyObject
* kwds
) {
48 PakfireObject
* self
= (PakfireObject
*)type
->tp_alloc(type
, 0);
53 self
->callbacks
.log
= NULL
;
54 self
->callbacks
.confirm
= NULL
;
57 return (PyObject
*)self
;
60 static void Pakfire_log_callback(void* data
, int priority
, const char* file
, int line
,
61 const char* fn
, const char* format
, va_list args
) {
62 PyObject
* callback
= (PyObject
*)data
;
63 PyObject
* exception
= NULL
;
65 // Do nothing if callback isn't set
69 // Translate priority to Python logging priorities
83 // Drop messages of an unknown priority
88 PyObject
* tuple
= NULL
;
89 PyObject
* result
= NULL
;
93 int r
= vasprintf(&buffer
, format
, args
);
97 // Build a tuple with the priority and the log message
98 tuple
= Py_BuildValue("(is)", priority
, buffer
);
103 result
= PyObject_CallObject(callback
, tuple
);
107 We cannot really catch any Python errors here, since we cannot send
108 any error codes up the chain.
110 So, in order to debug the problem, We will check if an exception has
111 occurred and if so, print it to the console.
113 exception
= PyErr_Occurred();
123 static int Pakfire_confirm_callback(struct pakfire
* pakfire
, void* data
,
124 const char* message
, const char* question
) {
125 PyObject
* callback
= (PyObject
*)data
;
128 // Do nothing if callback isn't set
132 PyObject
* args
= Py_BuildValue("(ss)", message
, question
);
136 PyObject
* result
= PyObject_CallObject(callback
, args
);
138 // Extract return code
139 if (PyLong_Check(result
))
140 r
= PyLong_AsLong(result
);
148 static int Pakfire_init(PakfireObject
* self
, PyObject
* args
, PyObject
* kwds
) {
158 const char* path
= NULL
;
159 const char* arch
= NULL
;
160 const char* conf
= NULL
;
163 if (!PyArg_ParseTupleAndKeywords(args
, kwds
, "|zzOpzO", kwlist
,
164 &path
, &arch
, &self
->callbacks
.log
, &offline
, &conf
, &self
->callbacks
.confirm
))
167 // Check if log callback is callable
168 if (self
->callbacks
.log
&& !PyCallable_Check(self
->callbacks
.log
)) {
169 PyErr_SetString(PyExc_TypeError
, "logger must be callable\n");
173 // Check if confirm callback is callable
174 if (self
->callbacks
.confirm
&& !PyCallable_Check(self
->callbacks
.confirm
)) {
175 PyErr_SetString(PyExc_TypeError
, "Confirm callback is not callable");
181 // Enable offline mode
183 flags
|= PAKFIRE_FLAGS_OFFLINE
;
185 // Configure callbacks
186 if (self
->callbacks
.log
)
187 Py_INCREF(self
->callbacks
.log
);
189 // Create a new Pakfire instance
190 int r
= pakfire_create(&self
->pakfire
, path
, arch
, conf
, flags
,
191 LOG_DEBUG
, Pakfire_log_callback
, self
->callbacks
.log
);
194 // Invalid architecture or path
196 PyErr_SetString(PyExc_ValueError
, "Invalid architecture or path");
201 PyErr_SetFromErrno(PyExc_OSError
);
207 // Configure confirm callback
208 if (self
->callbacks
.confirm
) {
209 pakfire_set_confirm_callback(self
->pakfire
,
210 Pakfire_confirm_callback
, self
->callbacks
.confirm
);
212 Py_INCREF(self
->callbacks
.confirm
);
218 static void Pakfire_dealloc(PakfireObject
* self
) {
220 // Reset log callback
221 if (self
->callbacks
.log
) {
222 pakfire_set_log_callback(self
->pakfire
, NULL
, NULL
);
223 Py_DECREF(self
->callbacks
.log
);
226 // Reset confirm callback
227 if (self
->callbacks
.confirm
) {
228 pakfire_set_confirm_callback(self
->pakfire
, NULL
, NULL
);
229 Py_DECREF(self
->callbacks
.confirm
);
232 pakfire_unref(self
->pakfire
);
235 Py_TYPE(self
)->tp_free((PyObject
*)self
);
238 static PyObject
* Pakfire_repr(PakfireObject
* self
) {
239 const char* path
= pakfire_get_path(self
->pakfire
);
240 const char* arch
= pakfire_get_arch(self
->pakfire
);
242 return PyUnicode_FromFormat("<_pakfire.Pakfire %s (%s)>", path
, arch
);
245 static PyObject
* Pakfire_get_path(PakfireObject
* self
) {
246 const char* path
= pakfire_get_path(self
->pakfire
);
248 return PyUnicode_FromString(path
);
251 static PyObject
* Pakfire_get_arch(PakfireObject
* self
) {
252 const char* arch
= pakfire_get_arch(self
->pakfire
);
254 return PyUnicode_FromString(arch
);
257 static PyObject
* Pakfire_get_repo(PakfireObject
* self
, PyObject
* args
) {
258 const char* name
= NULL
;
260 if (!PyArg_ParseTuple(args
, "s", &name
))
263 struct pakfire_repo
* repo
= pakfire_get_repo(self
->pakfire
, name
);
267 PyObject
* obj
= new_repo(&RepoType
, repo
);
268 pakfire_repo_unref(repo
);
273 static void Pakfire_status_callback(struct pakfire
* pakfire
, void* data
,
274 int progress
, const char* status
) {
275 PyObject
* callback
= (PyObject
*)data
;
277 // Do not attempt to call nothing
282 PyObject
* args
= Py_BuildValue("(is)", progress
, status
);
287 PyObject
* result
= PyObject_CallObject(callback
, args
);
293 static int convert_packages(PyObject
* object
, void* address
) {
294 char*** packages
= (char***)address
;
296 // Called for cleanup
300 // Nothing to do when object is None
301 if (object
== Py_None
)
302 return Py_CLEANUP_SUPPORTED
;
304 if (!PySequence_Check(object
)) {
305 PyErr_SetString(PyExc_ValueError
, "Packages must be a sequence");
309 const unsigned int length
= PySequence_Length(object
);
311 return Py_CLEANUP_SUPPORTED
;
314 *packages
= calloc(length
+ 1, sizeof(*packages
));
316 PyErr_SetFromErrno(PyExc_OSError
);
320 for (unsigned int i
= 0; i
< length
; i
++) {
321 PyObject
* item
= PySequence_GetItem(object
, i
);
323 // Check if input is a string
324 if (!PyUnicode_Check(item
)) {
327 PyErr_SetString(PyExc_AttributeError
, "Expected a string");
332 const char* package
= PyUnicode_AsUTF8(item
);
338 // Add package to array
339 (*packages
)[i
] = strdup(package
);
340 if (!(*packages
)[i
]) {
349 return Py_CLEANUP_SUPPORTED
;
353 for (char** package
= *packages
; *package
; package
++)
361 static PyObject
* Pakfire_install(PakfireObject
* self
, PyObject
* args
, PyObject
* kwargs
) {
365 "without_recommended",
371 char** packages
= NULL
;
373 int without_recommended
= 0;
374 int allow_uninstall
= 0;
375 int allow_downgrade
= 0;
376 int solver_flags
= 0;
377 int transaction_flags
= 0;
378 PyObject
* status_callback
= NULL
;
380 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "O&|$ppppO", kwlist
,
381 convert_packages
, &packages
, &dryrun
, &without_recommended
, &allow_uninstall
,
382 &allow_downgrade
, &status_callback
))
385 // Check if callback is callable
386 if (status_callback
&& !PyCallable_Check(status_callback
)) {
387 PyErr_SetString(PyExc_TypeError
, "status_callback must be callable");
391 // Enable dry-run mode
393 transaction_flags
|= PAKFIRE_TRANSACTION_DRY_RUN
;
395 // Do not install recommended packages
396 if (without_recommended
)
397 solver_flags
|= PAKFIRE_REQUEST_WITHOUT_RECOMMENDED
;
399 // Can the solver uninstall packages?
401 solver_flags
|= PAKFIRE_REQUEST_ALLOW_UNINSTALL
;
403 // Can the solver downgrade packages?
405 solver_flags
|= PAKFIRE_REQUEST_ALLOW_DOWNGRADE
;
407 // Run pakfire_install
408 int r
= pakfire_install(self
->pakfire
, transaction_flags
, solver_flags
,
409 (const char**)packages
, NULL
, 0, NULL
, Pakfire_status_callback
, status_callback
);
411 PyErr_SetFromErrno(PyExc_OSError
);
414 for (char** package
= packages
; *package
; package
++)
425 static PyObject
* Pakfire_erase(PakfireObject
* self
, PyObject
* args
, PyObject
* kwargs
) {
433 char** packages
= NULL
;
435 int keep_dependencies
= 0;
436 int transaction_flags
= 0;
438 PyObject
* status_callback
= NULL
;
440 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "O&|$ppO", kwlist
,
441 convert_packages
, &packages
, &dryrun
, &keep_dependencies
, &status_callback
))
444 // Check if callback is callable
445 if (status_callback
&& !PyCallable_Check(status_callback
)) {
446 PyErr_SetString(PyExc_TypeError
, "status_callback must be callable");
451 transaction_flags
|= PAKFIRE_TRANSACTION_DRY_RUN
;
453 if (keep_dependencies
)
454 flags
|= PAKFIRE_REQUEST_KEEP_DEPS
;
457 int r
= pakfire_erase(self
->pakfire
, transaction_flags
, 0, (const char**)packages
,
458 NULL
, flags
, NULL
, Pakfire_status_callback
, status_callback
);
460 PyErr_SetFromErrno(PyExc_OSError
);
463 for (char** package
= packages
; *package
; package
++)
474 static PyObject
* Pakfire_update(PakfireObject
* self
, PyObject
* args
, PyObject
* kwargs
) {
484 char** packages
= NULL
;
485 char** excludes
= NULL
;
487 int allow_uninstall
= 0;
488 int allow_downgrade
= 0;
489 int solver_flags
= 0;
490 int transaction_flags
= 0;
491 PyObject
* status_callback
= NULL
;
493 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "O&|$O&ppO", kwlist
,
494 convert_packages
, &packages
, convert_packages
, &excludes
,
495 &allow_uninstall
, &allow_downgrade
, &status_callback
))
498 // Check if callback is callable
499 if (status_callback
&& !PyCallable_Check(status_callback
)) {
500 PyErr_SetString(PyExc_TypeError
, "status_callback must be callable");
505 transaction_flags
= PAKFIRE_TRANSACTION_DRY_RUN
;
507 // Can the solver uninstall packages?
509 solver_flags
|= PAKFIRE_REQUEST_ALLOW_UNINSTALL
;
511 // Can the solver downgrade packages?
513 solver_flags
|= PAKFIRE_REQUEST_ALLOW_DOWNGRADE
;
515 // Run pakfire_update
516 int r
= pakfire_update(self
->pakfire
, transaction_flags
, solver_flags
,
517 (const char**)packages
, (const char**)excludes
, 0, NULL
,
518 Pakfire_status_callback
, status_callback
);
520 PyErr_SetFromErrno(PyExc_OSError
);
523 for (char** package
= packages
; *package
; package
++)
529 for (char** exclude
= excludes
; *exclude
; exclude
++)
540 static PyObject
* Pakfire_keys_to_list(struct pakfire_key
** keys
) {
541 PyObject
* list
= PyList_New(0);
547 // Push all keys onto the list
548 for (struct pakfire_key
** key
= keys
; *key
; key
++) {
549 PyObject
* object
= new_key(&KeyType
, *key
);
553 PyList_Append(list
, object
);
564 static PyObject
* Pakfire_get_keys(PakfireObject
* self
) {
565 struct pakfire_key
** keys
= NULL
;
567 int r
= pakfire_list_keys(self
->pakfire
, &keys
);
569 PyErr_SetFromErrno(PyExc_OSError
);
573 // Convert keys to list
574 PyObject
* list
= Pakfire_keys_to_list(keys
);
578 for (struct pakfire_key
** key
= keys
; *key
; key
++)
579 pakfire_key_unref(*key
);
586 static PyObject
* Pakfire_get_key(PakfireObject
* self
, PyObject
* args
) {
587 const char* pattern
= NULL
;
589 if (!PyArg_ParseTuple(args
, "s", &pattern
))
592 // Try finding the key
593 struct pakfire_key
* key
= pakfire_key_get(self
->pakfire
, pattern
);
597 PyObject
* object
= new_key(&KeyType
, key
);
598 pakfire_key_unref(key
);
603 static PyObject
* Pakfire_generate_key(PakfireObject
* self
, PyObject
* args
, PyObject
* kwds
) {
604 char* kwlist
[] = { "userid", "algorithm", NULL
};
605 struct pakfire_key
* key
= NULL
;
606 const char* userid
= NULL
;
607 const char* algo
= NULL
;
609 if (!PyArg_ParseTupleAndKeywords(args
, kwds
, "s|$z", kwlist
, &userid
, &algo
))
612 // Generate a new key
613 int r
= pakfire_key_generate(&key
, self
->pakfire
, algo
, userid
);
615 PyErr_SetFromErrno(PyExc_OSError
);
619 PyObject
* object
= new_key(&KeyType
, key
);
620 pakfire_key_unref(key
);
625 static PyObject
* Pakfire_import_key(PakfireObject
* self
, PyObject
* args
) {
626 PyObject
* object
= NULL
;
628 if (!PyArg_ParseTuple(args
, "O", &object
))
631 // Get a file descriptor from object
632 int fd
= PyObject_AsFileDescriptor(object
);
637 FILE* f
= fdopen(fd
, "r");
639 PyErr_SetFromErrno(PyExc_OSError
);
643 struct pakfire_key
** keys
= NULL
;
645 // Import keys from f
646 int r
= pakfire_key_import(self
->pakfire
, f
, &keys
);
648 PyErr_SetFromErrno(PyExc_OSError
);
652 // Convert keys to list
653 PyObject
* list
= Pakfire_keys_to_list(keys
);
656 for (struct pakfire_key
** key
= keys
; *key
; key
++)
657 pakfire_key_unref(*key
);
663 static PyObject
* Pakfire_fetch_key(PakfireObject
* self
, PyObject
* args
, PyObject
* kwds
) {
664 char* kwlist
[] = { "userid", "fingerprint", NULL
};
665 struct pakfire_key
* key
= NULL
;
666 const char* userid
= NULL
;
667 const char* fingerprint
= NULL
;
669 if (!PyArg_ParseTupleAndKeywords(args
, kwds
, "|$zz", kwlist
, &userid
, &fingerprint
))
673 int r
= pakfire_key_fetch(&key
, self
->pakfire
, userid
, fingerprint
);
675 PyErr_SetFromErrno(PyExc_OSError
);
681 PyObject
* object
= new_key(&KeyType
, key
);
682 pakfire_key_unref(key
);
690 static PyObject
* Pakfire_whatprovides(PakfireObject
* self
, PyObject
* args
) {
691 const char* provides
= NULL
;
692 struct pakfire_packagelist
* list
= NULL
;
694 if (!PyArg_ParseTuple(args
, "s", &provides
))
697 int r
= pakfire_whatprovides(self
->pakfire
, provides
, 0, &list
);
699 PyErr_SetFromErrno(PyExc_OSError
);
703 PyObject
* obj
= PyList_FromPackageList(list
);
704 pakfire_packagelist_unref(list
);
709 static PyObject
* Pakfire_whatrequires(PakfireObject
* self
, PyObject
* args
) {
710 const char* requires
= NULL
;
711 struct pakfire_packagelist
* list
= NULL
;
713 if (!PyArg_ParseTuple(args
, "s", &requires
))
716 int r
= pakfire_whatrequires(self
->pakfire
, requires
, 0, &list
);
718 PyErr_SetFromErrno(PyExc_OSError
);
722 PyObject
* obj
= PyList_FromPackageList(list
);
723 pakfire_packagelist_unref(list
);
728 static PyObject
* Pakfire_search(PakfireObject
* self
, PyObject
* args
, PyObject
* kwds
) {
729 char* kwlist
[] = { "pattern", "name_only", NULL
};
730 struct pakfire_packagelist
* list
= NULL
;
731 const char* pattern
= NULL
;
735 if (!PyArg_ParseTupleAndKeywords(args
, kwds
, "s|$p", kwlist
, &pattern
, &name_only
))
738 // Search for package names only
740 flags
|= PAKFIRE_SEARCH_NAME_ONLY
;
742 int r
= pakfire_search(self
->pakfire
, pattern
, flags
, &list
);
744 PyErr_SetFromErrno(PyExc_OSError
);
748 PyObject
* obj
= PyList_FromPackageList(list
);
749 pakfire_packagelist_unref(list
);
754 static PyObject
* Pakfire_version_compare(PakfireObject
* self
, PyObject
* args
) {
755 const char* evr1
= NULL
;
756 const char* evr2
= NULL
;
758 if (!PyArg_ParseTuple(args
, "ss", &evr1
, &evr2
))
761 int cmp
= pakfire_version_compare(self
->pakfire
, evr1
, evr2
);
763 return PyLong_FromLong(cmp
);
766 static int __Pakfire_logging_callback(struct pakfire
* pakfire
, void* data
,
767 int priority
, const char* line
, size_t length
) {
768 PyObject
* callback
= (PyObject
*)data
;
771 // Do nothing if callback isn't set
775 // Translate priority to Python logging priorities
786 // Remove the trailing newline
787 if (line
&& line
[length
- 1] == '\n')
790 // Create tuple with arguments for the callback function
791 PyObject
* args
= Py_BuildValue("(is#)", priority
, line
, (Py_ssize_t
)length
);
795 PyObject
* result
= PyObject_CallObject(callback
, args
);
796 if (result
&& PyLong_Check(result
)) {
797 r
= PyLong_AsLong(result
);
806 static PyObject
* Pakfire_execute(PakfireObject
* self
, PyObject
* args
, PyObject
* kwds
) {
817 struct pakfire_jail
* jail
= NULL
;
818 const char** argv
= NULL
;
821 PyObject
* ret
= NULL
;
824 PyObject
* command
= NULL
;
825 PyObject
* environ
= NULL
;
826 PyObject
* bind
= NULL
;
827 PyObject
* logging_callback
= NULL
;
829 int return_output
= 0;
831 if (!PyArg_ParseTupleAndKeywords(args
, kwds
, "O|OOOip", kwlist
, &command
, &environ
,
832 &bind
, &logging_callback
, &nice
, &return_output
))
835 // Check if command is a list
836 if (!PyList_Check(command
)) {
837 PyErr_SetString(PyExc_TypeError
, "command must be a list");
841 const ssize_t command_length
= PyList_Size(command
);
843 // Check if command is not empty
844 if (command_length
== 0) {
845 PyErr_SetString(PyExc_ValueError
, "command is empty");
850 argv
= calloc(command_length
+ 1, sizeof(*argv
));
854 // All arguments in command must be strings
855 for (unsigned int i
= 0; i
< command_length
; i
++) {
856 PyObject
* item
= PyList_GET_ITEM(command
, i
);
858 if (!PyUnicode_Check(item
)) {
859 PyErr_Format(PyExc_TypeError
, "Item %u in command is not a string", i
);
864 argv
[i
] = PyUnicode_AsUTF8(item
);
867 // Check if bind is a sequence
868 if (bind
&& !PySequence_Check(bind
)) {
869 PyErr_SetString(PyExc_ValueError
, "bind is not a sequence");
874 r
= pakfire_jail_create(&jail
, self
->pakfire
, flags
);
876 PyErr_SetFromErrno(PyExc_OSError
);
880 // Set logging callback
881 if (logging_callback
) {
882 if (!PyCallable_Check(logging_callback
)) {
883 PyErr_SetString(PyExc_TypeError
, "logging_callback must be callable\n");
887 pakfire_jail_set_log_callback(jail
, __Pakfire_logging_callback
, logging_callback
);
892 r
= pakfire_jail_nice(jail
, nice
);
894 PyErr_SetFromErrno(PyExc_OSError
);
899 PyObject
* key
= NULL
;
900 PyObject
* value
= NULL
;
903 // Parse the environment
905 // Check if environ is a dictionary
906 if (!PyDict_Check(environ
)) {
907 PyErr_SetString(PyExc_TypeError
, "environ must be a dictionary");
911 // All keys and values must be strings
912 while (PyDict_Next(environ
, &p
, &key
, &value
)) {
913 if (!PyUnicode_Check(key
) || !PyUnicode_Check(value
)) {
914 PyErr_SetString(PyExc_TypeError
, "Environment contains a non-string object");
918 // Set environment value
919 r
= pakfire_jail_set_env(jail
, PyUnicode_AsUTF8(key
), PyUnicode_AsUTF8(value
));
921 PyErr_SetFromErrno(PyExc_OSError
);
927 const Py_ssize_t num_bind
= PySequence_Length(bind
);
930 for (unsigned int i
= 0; i
< num_bind
; i
++) {
931 PyObject
* b
= PySequence_ITEM(bind
, i
);
935 // Check if this is a Unicode object
936 if (!PyUnicode_Check(b
)) {
937 PyErr_SetString(PyExc_ValueError
, "bind contains a non-Unicode object");
942 const char* path
= PyUnicode_AsUTF8(b
);
945 r
= pakfire_jail_bind(jail
, path
, path
, 0);
947 PyErr_SetFromErrno(PyExc_OSError
);
956 r
= pakfire_jail_exec(jail
, argv
, (return_output
) ? &output
: NULL
);
958 // If the return code was negative, we had some internal error
960 PyErr_SetFromErrno(PyExc_OSError
);
963 // Otherwise the executed command returned some error code
965 PyObject
* code
= PyLong_FromLong(r
);
967 // Raise CommandExecutionError
968 PyErr_SetObject(PyExc_CommandExecutionError
, code
);
974 // The process has exited successfully
976 // Did the user request the output?
978 // Return the buffer as bytes
980 ret
= PyBytes_FromString(output
);
983 // Otherwise just return None
996 // Dereference the logging callback
997 // It might happen that the jail is not being freed because something else is
998 // holding a reference to it. We will however lose the reference to the logging
999 // function here which is why we reset it.
1000 pakfire_jail_set_log_callback(jail
, NULL
, NULL
);
1002 pakfire_jail_unref(jail
);
1008 static PyObject
* Pakfire_dist(PakfireObject
* self
, PyObject
* args
) {
1009 const char* path
= NULL
;
1010 const char* target
= NULL
;
1011 char* result
= NULL
;
1013 if (!PyArg_ParseTuple(args
, "s|z", &path
, &target
))
1016 int r
= pakfire_dist(self
->pakfire
, path
, target
, &result
);
1018 PyErr_SetFromErrno(PyExc_OSError
);
1022 PyObject
* ret
= PyUnicode_FromString(result
);
1028 static PyObject
* Pakfire_copy_in(PakfireObject
* self
, PyObject
* args
) {
1029 const char* src
= NULL
;
1030 const char* dst
= NULL
;
1032 if (!PyArg_ParseTuple(args
, "ss", &src
, &dst
))
1035 int r
= pakfire_copy_in(self
->pakfire
, src
, dst
);
1037 PyErr_SetFromErrno(PyExc_OSError
);
1044 static PyObject
* Pakfire_copy_out(PakfireObject
* self
, PyObject
* args
) {
1045 const char* src
= NULL
;
1046 const char* dst
= NULL
;
1048 if (!PyArg_ParseTuple(args
, "ss", &src
, &dst
))
1051 int r
= pakfire_copy_out(self
->pakfire
, src
, dst
);
1053 PyErr_SetFromErrno(PyExc_OSError
);
1060 static PyObject
* Pakfire_get_repos(PakfireObject
* self
) {
1061 struct pakfire_repolist
* repos
= pakfire_get_repos(self
->pakfire
);
1063 PyErr_SetFromErrno(PyExc_OSError
);
1067 const size_t l
= pakfire_repolist_size(repos
);
1069 PyObject
* list
= PyList_New(l
);
1073 for (unsigned int i
= 0; i
< l
; i
++) {
1074 struct pakfire_repo
* repo
= pakfire_repolist_get(repos
, i
);
1078 PyObject
* obj
= new_repo(&RepoType
, repo
);
1079 PyList_SET_ITEM(list
, i
, obj
);
1081 pakfire_repo_unref(repo
);
1085 pakfire_repolist_unref(repos
);
1090 static PyObject
* execute_return_value(int r
) {
1091 // Raise an OS error if r < 0
1095 PyErr_SetFromErrno(PyExc_OSError
);
1098 // Raise exception when the command failed
1100 PyObject
* code
= PyLong_FromLong(r
);
1102 PyErr_SetObject(PyExc_CommandExecutionError
, code
);
1111 static PyObject
* Pakfire_build(PakfireObject
* self
, PyObject
* args
, PyObject
* kwargs
) {
1120 const char* path
= NULL
;
1121 const char* build_id
= NULL
;
1122 int disable_snapshot
= 0;
1123 int disable_ccache
= 0;
1125 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "s|zpp", kwlist
, &path
, &build_id
,
1126 &disable_snapshot
, &disable_ccache
))
1131 // Disable snapshot if requested
1132 if (disable_snapshot
)
1133 flags
|= PAKFIRE_BUILD_DISABLE_SNAPSHOT
;
1135 // Disable ccache if requested
1137 flags
|= PAKFIRE_BUILD_DISABLE_CCACHE
;
1140 int r
= pakfire_build(self
->pakfire
, path
, NULL
, build_id
, flags
);
1142 return execute_return_value(r
);
1145 static PyObject
* Pakfire_shell(PakfireObject
* self
, PyObject
* args
, PyObject
* kwargs
) {
1150 char** packages
= NULL
;
1153 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|O&", kwlist
, convert_packages
, &packages
))
1156 int r
= pakfire_shell(self
->pakfire
, (const char**)packages
);
1158 return execute_return_value(r
);
1161 static PyObject
* Pakfire_clean(PakfireObject
* self
) {
1162 int r
= pakfire_clean(self
->pakfire
, 0);
1164 PyErr_SetFromErrno(PyExc_OSError
);
1171 static PyObject
* Pakfire_refresh(PakfireObject
* self
, PyObject
* args
) {
1174 if (!PyArg_ParseTuple(args
, "|p", &force
))
1177 int r
= pakfire_refresh(self
->pakfire
, force
);
1179 PyErr_SetFromErrno(PyExc_OSError
);
1186 static PyObject
* Pakfire_check(PakfireObject
* self
) {
1187 struct pakfire_filelist
* errors
= NULL
;
1190 // Allocate a filelist for errors
1191 r
= pakfire_filelist_create(&errors
, self
->pakfire
);
1196 r
= pakfire_check(self
->pakfire
, errors
);
1200 const size_t num_errors
= pakfire_filelist_size(errors
);
1202 // Did we find any errors?
1204 PyObject
* _errors
= PyList_FromFileList(errors
);
1208 pakfire_filelist_unref(errors
);
1210 // Raise CheckFileVerificationError
1211 PyErr_SetObject(PyExc_CheckFileVerificationError
, _errors
);
1216 pakfire_filelist_unref(errors
);
1222 pakfire_filelist_unref(errors
);
1224 // Raise exception from errno
1225 PyErr_SetFromErrno(PyExc_OSError
);
1229 static PyObject
* Pakfire_sync(PakfireObject
* self
, PyObject
* args
, PyObject
* kwargs
) {
1235 int keep_orphaned
= 0;
1237 PyObject
* status_callback
= NULL
;
1239 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|$pO", kwlist
,
1240 &keep_orphaned
, &status_callback
))
1244 flags
|= PAKFIRE_REQUEST_KEEP_ORPHANED
;
1246 int r
= pakfire_sync(self
->pakfire
, 0, flags
, NULL
,
1247 Pakfire_status_callback
, status_callback
);
1249 PyErr_SetFromErrno(PyExc_OSError
);
1256 static PyObject
* Pakfire_open(PakfireObject
* self
, PyObject
* args
) {
1257 struct pakfire_archive
* archive
= NULL
;
1258 const char* path
= NULL
;
1260 if (!PyArg_ParseTuple(args
, "s", &path
))
1263 int r
= pakfire_archive_open(&archive
, self
->pakfire
, path
);
1265 PyErr_SetFromErrno(PyExc_OSError
);
1269 // Create Python object
1270 PyObject
* object
= new_archive(&ArchiveType
, archive
);
1271 pakfire_archive_unref(archive
);
1276 static PyObject
* Pakfire_repo_compose(PakfireObject
* self
, PyObject
* args
, PyObject
* kwargs
) {
1277 char* kwlist
[] = { "path", "files", NULL
};
1278 const char* path
= NULL
;
1279 PyObject
* list
= NULL
;
1281 PyObject
* ret
= NULL
;
1283 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "sO", kwlist
, &path
, &list
))
1286 // List must be a sequence
1287 if (!PySequence_Check(list
)) {
1288 PyErr_SetString(PyExc_ValueError
, "Expected a sequence.");
1292 const int flags
= 0;
1294 // How many new files do we have?
1295 ssize_t num_files
= PySequence_Length(list
);
1299 // Allocate files array
1300 const char** files
= calloc(num_files
+ 1, sizeof(*files
));
1302 PyErr_SetFromErrno(PyExc_OSError
);
1306 for (int i
= 0; i
< num_files
; i
++) {
1307 PyObject
* file
= PySequence_GetItem(list
, i
);
1311 // Check if file is a Unicode object
1312 if (!PyUnicode_Check(file
)) {
1313 PyErr_SetString(PyExc_ValueError
, "Expected a string.");
1317 // Add pointer to string to files array
1318 files
[i
] = PyUnicode_AsUTF8(file
);
1325 int r
= pakfire_repo_compose(self
->pakfire
, path
, flags
, files
);
1327 PyErr_SetFromErrno(PyExc_OSError
);
1331 // Return None on success
1342 static struct PyMethodDef Pakfire_methods
[] = {
1345 (PyCFunction
)Pakfire_build
,
1346 METH_VARARGS
|METH_KEYWORDS
,
1351 (PyCFunction
)Pakfire_check
,
1357 (PyCFunction
)Pakfire_clean
,
1363 (PyCFunction
)Pakfire_copy_in
,
1369 (PyCFunction
)Pakfire_copy_out
,
1375 (PyCFunction
)Pakfire_dist
,
1381 (PyCFunction
)Pakfire_erase
,
1382 METH_VARARGS
|METH_KEYWORDS
,
1387 (PyCFunction
)Pakfire_execute
,
1388 METH_VARARGS
|METH_KEYWORDS
,
1393 (PyCFunction
)Pakfire_fetch_key
,
1394 METH_VARARGS
|METH_KEYWORDS
,
1399 (PyCFunction
)Pakfire_generate_key
,
1400 METH_VARARGS
|METH_KEYWORDS
,
1405 (PyCFunction
)Pakfire_get_key
,
1411 (PyCFunction
)Pakfire_get_repo
,
1417 (PyCFunction
)Pakfire_import_key
,
1423 (PyCFunction
)Pakfire_install
,
1424 METH_VARARGS
|METH_KEYWORDS
,
1429 (PyCFunction
)Pakfire_open
,
1435 (PyCFunction
)Pakfire_refresh
,
1441 (PyCFunction
)Pakfire_repo_compose
,
1442 METH_VARARGS
|METH_KEYWORDS
,
1447 (PyCFunction
)Pakfire_search
,
1448 METH_VARARGS
|METH_KEYWORDS
,
1453 (PyCFunction
)Pakfire_shell
,
1454 METH_VARARGS
|METH_KEYWORDS
,
1459 (PyCFunction
)Pakfire_sync
,
1460 METH_VARARGS
|METH_KEYWORDS
,
1465 (PyCFunction
)Pakfire_update
,
1466 METH_VARARGS
|METH_KEYWORDS
,
1471 (PyCFunction
)Pakfire_version_compare
,
1477 (PyCFunction
)Pakfire_whatprovides
,
1483 (PyCFunction
)Pakfire_whatrequires
,
1490 static struct PyGetSetDef Pakfire_getsetters
[] = {
1493 (getter
)Pakfire_get_arch
,
1500 (getter
)Pakfire_get_keys
,
1507 (getter
)Pakfire_get_path
,
1514 (getter
)Pakfire_get_repos
,
1522 PyTypeObject PakfireType
= {
1523 PyVarObject_HEAD_INIT(NULL
, 0)
1524 tp_name
: "_pakfire.Pakfire",
1525 tp_basicsize
: sizeof(PakfireObject
),
1526 tp_flags
: Py_TPFLAGS_DEFAULT
|Py_TPFLAGS_BASETYPE
,
1527 tp_new
: Pakfire_new
,
1528 tp_dealloc
: (destructor
)Pakfire_dealloc
,
1529 tp_init
: (initproc
)Pakfire_init
,
1530 tp_doc
: "Pakfire object",
1531 tp_methods
: Pakfire_methods
,
1532 tp_getset
: Pakfire_getsetters
,
1533 tp_repr
: (reprfunc
)Pakfire_repr
,