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/transaction.h>
39 #include <pakfire/util.h>
48 static PyObject
* Pakfire_new(PyTypeObject
* type
, PyObject
* args
, PyObject
* kwds
) {
49 PakfireObject
* self
= (PakfireObject
*)type
->tp_alloc(type
, 0);
54 self
->callbacks
.log
= NULL
;
55 self
->callbacks
.confirm
= NULL
;
58 return (PyObject
*)self
;
61 static void Pakfire_log_callback(void* data
, int priority
, const char* file
, int line
,
62 const char* fn
, const char* format
, va_list args
) {
63 PyObject
* callback
= (PyObject
*)data
;
64 PyObject
* exception
= NULL
;
66 // Do nothing if callback isn't set
70 // Translate priority to Python logging priorities
84 // Drop messages of an unknown priority
89 PyObject
* tuple
= NULL
;
90 PyObject
* result
= NULL
;
94 int r
= vasprintf(&buffer
, format
, args
);
98 // Build a tuple with the priority and the log message
99 tuple
= Py_BuildValue("(is)", priority
, buffer
);
104 result
= PyObject_CallObject(callback
, tuple
);
108 We cannot really catch any Python errors here, since we cannot send
109 any error codes up the chain.
111 So, in order to debug the problem, We will check if an exception has
112 occurred and if so, print it to the console.
114 exception
= PyErr_Occurred();
124 static int Pakfire_confirm_callback(struct pakfire
* pakfire
, void* data
,
125 const char* message
, const char* question
) {
126 PyObject
* callback
= (PyObject
*)data
;
129 // Do nothing if callback isn't set
133 PyObject
* args
= Py_BuildValue("(ss)", message
, question
);
137 PyObject
* result
= PyObject_CallObject(callback
, args
);
139 // If the callback raised an exception, we will ignore it and indicate
140 // that an error happened, but we cannot re-raise the exception
146 // Set the return code
147 if (result
== Py_True
)
159 static int Pakfire_init(PakfireObject
* self
, PyObject
* args
, PyObject
* kwds
) {
169 const char* path
= NULL
;
170 const char* arch
= NULL
;
171 const char* conf
= NULL
;
174 if (!PyArg_ParseTupleAndKeywords(args
, kwds
, "|zzOpzO", kwlist
,
175 &path
, &arch
, &self
->callbacks
.log
, &offline
, &conf
, &self
->callbacks
.confirm
))
178 // Check if log callback is callable
179 if (self
->callbacks
.log
&& !PyCallable_Check(self
->callbacks
.log
)) {
180 PyErr_SetString(PyExc_TypeError
, "logger must be callable\n");
184 // Check if confirm callback is callable
185 if (self
->callbacks
.confirm
&& !PyCallable_Check(self
->callbacks
.confirm
)) {
186 PyErr_SetString(PyExc_TypeError
, "Confirm callback is not callable");
192 // Enable offline mode
194 flags
|= PAKFIRE_FLAGS_OFFLINE
;
196 // Configure callbacks
197 if (self
->callbacks
.log
)
198 Py_INCREF(self
->callbacks
.log
);
200 // Create a new Pakfire instance
201 int r
= pakfire_create(&self
->pakfire
, path
, arch
, conf
, flags
,
202 LOG_DEBUG
, Pakfire_log_callback
, self
->callbacks
.log
);
205 // Invalid architecture or path
207 PyErr_SetString(PyExc_ValueError
, "Invalid architecture or path");
212 PyErr_SetFromErrno(PyExc_OSError
);
218 // Configure confirm callback
219 if (self
->callbacks
.confirm
) {
220 pakfire_set_confirm_callback(self
->pakfire
,
221 Pakfire_confirm_callback
, self
->callbacks
.confirm
);
223 Py_INCREF(self
->callbacks
.confirm
);
229 static void Pakfire_dealloc(PakfireObject
* self
) {
231 // Reset log callback
232 if (self
->callbacks
.log
) {
233 pakfire_set_log_callback(self
->pakfire
, NULL
, NULL
);
234 Py_DECREF(self
->callbacks
.log
);
237 // Reset confirm callback
238 if (self
->callbacks
.confirm
) {
239 pakfire_set_confirm_callback(self
->pakfire
, NULL
, NULL
);
240 Py_DECREF(self
->callbacks
.confirm
);
243 pakfire_unref(self
->pakfire
);
246 Py_TYPE(self
)->tp_free((PyObject
*)self
);
249 static PyObject
* Pakfire_repr(PakfireObject
* self
) {
250 const char* path
= pakfire_get_path(self
->pakfire
);
251 const char* arch
= pakfire_get_arch(self
->pakfire
);
253 return PyUnicode_FromFormat("<_pakfire.Pakfire %s (%s)>", path
, arch
);
256 static PyObject
* Pakfire_get_path(PakfireObject
* self
) {
257 const char* path
= pakfire_get_path(self
->pakfire
);
259 return PyUnicode_FromString(path
);
262 static PyObject
* Pakfire_get_arch(PakfireObject
* self
) {
263 const char* arch
= pakfire_get_arch(self
->pakfire
);
265 return PyUnicode_FromString(arch
);
268 static PyObject
* Pakfire_get_repo(PakfireObject
* self
, PyObject
* args
) {
269 const char* name
= NULL
;
271 if (!PyArg_ParseTuple(args
, "s", &name
))
274 struct pakfire_repo
* repo
= pakfire_get_repo(self
->pakfire
, name
);
278 PyObject
* obj
= new_repo(&RepoType
, repo
);
279 pakfire_repo_unref(repo
);
284 static void Pakfire_status_callback(struct pakfire
* pakfire
, void* data
,
285 int progress
, const char* status
) {
286 PyObject
* callback
= (PyObject
*)data
;
288 // Do not attempt to call nothing
293 PyObject
* args
= Py_BuildValue("(is)", progress
, status
);
298 PyObject
* result
= PyObject_CallObject(callback
, args
);
304 static int convert_packages(PyObject
* object
, void* address
) {
305 char*** packages
= (char***)address
;
307 // Called for cleanup
311 // Nothing to do when object is None
312 if (object
== Py_None
)
313 return Py_CLEANUP_SUPPORTED
;
315 if (!PySequence_Check(object
)) {
316 PyErr_SetString(PyExc_ValueError
, "Packages must be a sequence");
320 const unsigned int length
= PySequence_Length(object
);
322 return Py_CLEANUP_SUPPORTED
;
325 *packages
= calloc(length
+ 1, sizeof(*packages
));
327 PyErr_SetFromErrno(PyExc_OSError
);
331 for (unsigned int i
= 0; i
< length
; i
++) {
332 PyObject
* item
= PySequence_GetItem(object
, i
);
334 // Check if input is a string
335 if (!PyUnicode_Check(item
)) {
338 PyErr_SetString(PyExc_AttributeError
, "Expected a string");
343 const char* package
= PyUnicode_AsUTF8(item
);
349 // Add package to array
350 (*packages
)[i
] = strdup(package
);
351 if (!(*packages
)[i
]) {
360 return Py_CLEANUP_SUPPORTED
;
364 for (char** package
= *packages
; *package
; package
++)
372 static PyObject
* Pakfire_install(PakfireObject
* self
, PyObject
* args
, PyObject
* kwargs
) {
376 "without_recommended",
382 char** packages
= NULL
;
384 int without_recommended
= 0;
385 int allow_uninstall
= 0;
386 int allow_downgrade
= 0;
387 int solver_flags
= 0;
388 int transaction_flags
= 0;
389 PyObject
* status_callback
= NULL
;
391 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "O&|$ppppO", kwlist
,
392 convert_packages
, &packages
, &dryrun
, &without_recommended
, &allow_uninstall
,
393 &allow_downgrade
, &status_callback
))
396 // Check if callback is callable
397 if (status_callback
&& !PyCallable_Check(status_callback
)) {
398 PyErr_SetString(PyExc_TypeError
, "status_callback must be callable");
402 // Enable dry-run mode
404 transaction_flags
|= PAKFIRE_TRANSACTION_DRY_RUN
;
406 // Do not install recommended packages
407 if (without_recommended
)
408 solver_flags
|= PAKFIRE_REQUEST_WITHOUT_RECOMMENDED
;
410 // Can the solver uninstall packages?
412 solver_flags
|= PAKFIRE_REQUEST_ALLOW_UNINSTALL
;
414 // Can the solver downgrade packages?
416 solver_flags
|= PAKFIRE_REQUEST_ALLOW_DOWNGRADE
;
418 // Run pakfire_install
419 int r
= pakfire_install(self
->pakfire
, transaction_flags
, solver_flags
,
420 (const char**)packages
, NULL
, 0, NULL
, Pakfire_status_callback
, status_callback
);
422 PyErr_SetFromErrno(PyExc_OSError
);
425 for (char** package
= packages
; *package
; package
++)
436 static PyObject
* Pakfire_erase(PakfireObject
* self
, PyObject
* args
, PyObject
* kwargs
) {
444 char** packages
= NULL
;
446 int keep_dependencies
= 0;
447 int transaction_flags
= 0;
449 PyObject
* status_callback
= NULL
;
451 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "O&|$ppO", kwlist
,
452 convert_packages
, &packages
, &dryrun
, &keep_dependencies
, &status_callback
))
455 // Check if callback is callable
456 if (status_callback
&& !PyCallable_Check(status_callback
)) {
457 PyErr_SetString(PyExc_TypeError
, "status_callback must be callable");
462 transaction_flags
|= PAKFIRE_TRANSACTION_DRY_RUN
;
464 if (keep_dependencies
)
465 flags
|= PAKFIRE_REQUEST_KEEP_DEPS
;
468 int r
= pakfire_erase(self
->pakfire
, transaction_flags
, 0, (const char**)packages
,
469 NULL
, flags
, NULL
, Pakfire_status_callback
, status_callback
);
471 PyErr_SetFromErrno(PyExc_OSError
);
474 for (char** package
= packages
; *package
; package
++)
485 static PyObject
* Pakfire_update(PakfireObject
* self
, PyObject
* args
, PyObject
* kwargs
) {
495 char** packages
= NULL
;
496 char** excludes
= NULL
;
498 int allow_uninstall
= 0;
499 int allow_downgrade
= 0;
500 int solver_flags
= 0;
501 int transaction_flags
= 0;
502 PyObject
* status_callback
= NULL
;
504 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "O&|$pO&ppO", kwlist
,
505 convert_packages
, &packages
, &dryrun
, convert_packages
, &excludes
,
506 &allow_uninstall
, &allow_downgrade
, &status_callback
))
509 // Check if callback is callable
510 if (status_callback
&& !PyCallable_Check(status_callback
)) {
511 PyErr_SetString(PyExc_TypeError
, "status_callback must be callable");
516 transaction_flags
= PAKFIRE_TRANSACTION_DRY_RUN
;
518 // Can the solver uninstall packages?
520 solver_flags
|= PAKFIRE_REQUEST_ALLOW_UNINSTALL
;
522 // Can the solver downgrade packages?
524 solver_flags
|= PAKFIRE_REQUEST_ALLOW_DOWNGRADE
;
526 // Run pakfire_update
527 int r
= pakfire_update(self
->pakfire
, transaction_flags
, solver_flags
,
528 (const char**)packages
, (const char**)excludes
, 0, NULL
,
529 Pakfire_status_callback
, status_callback
);
531 PyErr_SetFromErrno(PyExc_OSError
);
534 for (char** package
= packages
; *package
; package
++)
540 for (char** exclude
= excludes
; *exclude
; exclude
++)
551 static PyObject
* Pakfire_keys_to_list(struct pakfire_key
** keys
) {
552 PyObject
* list
= PyList_New(0);
558 // Push all keys onto the list
559 for (struct pakfire_key
** key
= keys
; *key
; key
++) {
560 PyObject
* object
= new_key(&KeyType
, *key
);
564 PyList_Append(list
, object
);
575 static PyObject
* Pakfire_get_keys(PakfireObject
* self
) {
576 struct pakfire_key
** keys
= NULL
;
578 int r
= pakfire_list_keys(self
->pakfire
, &keys
);
580 PyErr_SetFromErrno(PyExc_OSError
);
584 // Convert keys to list
585 PyObject
* list
= Pakfire_keys_to_list(keys
);
589 for (struct pakfire_key
** key
= keys
; *key
; key
++)
590 pakfire_key_unref(*key
);
597 static PyObject
* Pakfire_get_key(PakfireObject
* self
, PyObject
* args
) {
598 const char* pattern
= NULL
;
600 if (!PyArg_ParseTuple(args
, "s", &pattern
))
603 // Try finding the key
604 struct pakfire_key
* key
= pakfire_key_get(self
->pakfire
, pattern
);
608 PyObject
* object
= new_key(&KeyType
, key
);
609 pakfire_key_unref(key
);
614 static PyObject
* Pakfire_generate_key(PakfireObject
* self
, PyObject
* args
, PyObject
* kwds
) {
615 char* kwlist
[] = { "userid", "algorithm", NULL
};
616 struct pakfire_key
* key
= NULL
;
617 const char* userid
= NULL
;
618 const char* algo
= NULL
;
620 if (!PyArg_ParseTupleAndKeywords(args
, kwds
, "s|$z", kwlist
, &userid
, &algo
))
623 // Generate a new key
624 int r
= pakfire_key_generate(&key
, self
->pakfire
, algo
, userid
);
626 PyErr_SetFromErrno(PyExc_OSError
);
630 PyObject
* object
= new_key(&KeyType
, key
);
631 pakfire_key_unref(key
);
636 static PyObject
* Pakfire_import_key(PakfireObject
* self
, PyObject
* args
) {
637 PyObject
* object
= NULL
;
639 if (!PyArg_ParseTuple(args
, "O", &object
))
642 // Get a file descriptor from object
643 int fd
= PyObject_AsFileDescriptor(object
);
648 FILE* f
= fdopen(fd
, "r");
650 PyErr_SetFromErrno(PyExc_OSError
);
654 struct pakfire_key
** keys
= NULL
;
656 // Import keys from f
657 int r
= pakfire_key_import(self
->pakfire
, f
, &keys
);
659 PyErr_SetFromErrno(PyExc_OSError
);
663 // Convert keys to list
664 PyObject
* list
= Pakfire_keys_to_list(keys
);
667 for (struct pakfire_key
** key
= keys
; *key
; key
++)
668 pakfire_key_unref(*key
);
674 static PyObject
* Pakfire_fetch_key(PakfireObject
* self
, PyObject
* args
, PyObject
* kwds
) {
675 char* kwlist
[] = { "userid", "fingerprint", NULL
};
676 struct pakfire_key
* key
= NULL
;
677 const char* userid
= NULL
;
678 const char* fingerprint
= NULL
;
680 if (!PyArg_ParseTupleAndKeywords(args
, kwds
, "|$zz", kwlist
, &userid
, &fingerprint
))
684 int r
= pakfire_key_fetch(&key
, self
->pakfire
, userid
, fingerprint
);
686 PyErr_SetFromErrno(PyExc_OSError
);
692 PyObject
* object
= new_key(&KeyType
, key
);
693 pakfire_key_unref(key
);
701 static PyObject
* Pakfire_whatprovides(PakfireObject
* self
, PyObject
* args
) {
702 const char* provides
= NULL
;
703 struct pakfire_packagelist
* list
= NULL
;
705 if (!PyArg_ParseTuple(args
, "s", &provides
))
708 int r
= pakfire_whatprovides(self
->pakfire
, provides
, 0, &list
);
710 PyErr_SetFromErrno(PyExc_OSError
);
714 PyObject
* obj
= PyList_FromPackageList(list
);
715 pakfire_packagelist_unref(list
);
720 static PyObject
* Pakfire_whatrequires(PakfireObject
* self
, PyObject
* args
) {
721 const char* requires
= NULL
;
722 struct pakfire_packagelist
* list
= NULL
;
724 if (!PyArg_ParseTuple(args
, "s", &requires
))
727 int r
= pakfire_whatrequires(self
->pakfire
, requires
, 0, &list
);
729 PyErr_SetFromErrno(PyExc_OSError
);
733 PyObject
* obj
= PyList_FromPackageList(list
);
734 pakfire_packagelist_unref(list
);
739 static PyObject
* Pakfire_search(PakfireObject
* self
, PyObject
* args
, PyObject
* kwds
) {
740 char* kwlist
[] = { "pattern", "name_only", NULL
};
741 struct pakfire_packagelist
* list
= NULL
;
742 const char* pattern
= NULL
;
746 if (!PyArg_ParseTupleAndKeywords(args
, kwds
, "s|$p", kwlist
, &pattern
, &name_only
))
749 // Search for package names only
751 flags
|= PAKFIRE_SEARCH_NAME_ONLY
;
753 int r
= pakfire_search(self
->pakfire
, pattern
, flags
, &list
);
755 PyErr_SetFromErrno(PyExc_OSError
);
759 PyObject
* obj
= PyList_FromPackageList(list
);
760 pakfire_packagelist_unref(list
);
765 static PyObject
* Pakfire_version_compare(PakfireObject
* self
, PyObject
* args
) {
766 const char* evr1
= NULL
;
767 const char* evr2
= NULL
;
769 if (!PyArg_ParseTuple(args
, "ss", &evr1
, &evr2
))
772 int cmp
= pakfire_version_compare(self
->pakfire
, evr1
, evr2
);
774 return PyLong_FromLong(cmp
);
777 static int Pakfire_execute_output_callback(struct pakfire
* pakfire
, void* data
,
778 int priority
, const char* line
, size_t length
) {
779 PyObject
* callback
= (PyObject
*)data
;
782 // Do nothing if callback isn't set
786 // Translate priority to Python logging priorities
797 // Remove the trailing newline
798 if (line
&& line
[length
- 1] == '\n')
801 // Create tuple with arguments for the callback function
802 PyObject
* args
= Py_BuildValue("(is#)", priority
, line
, (Py_ssize_t
)length
);
806 PyObject
* result
= PyObject_CallObject(callback
, args
);
807 if (result
&& PyLong_Check(result
)) {
808 r
= PyLong_AsLong(result
);
817 static PyObject
* Pakfire_execute(PakfireObject
* self
, PyObject
* args
, PyObject
* kwds
) {
827 struct pakfire_jail
* jail
= NULL
;
828 const char** argv
= NULL
;
831 PyObject
* ret
= NULL
;
833 PyObject
* command
= NULL
;
834 PyObject
* environ
= NULL
;
835 PyObject
* bind
= NULL
;
836 PyObject
* callback
= NULL
;
839 if (!PyArg_ParseTupleAndKeywords(args
, kwds
, "O|OOOi", kwlist
, &command
, &environ
,
840 &bind
, &callback
, &nice
))
843 // Check if command is a list
844 if (!PyList_Check(command
)) {
845 PyErr_SetString(PyExc_TypeError
, "command must be a list");
849 const ssize_t command_length
= PyList_Size(command
);
851 // Check if command is not empty
852 if (command_length
== 0) {
853 PyErr_SetString(PyExc_ValueError
, "command is empty");
858 argv
= calloc(command_length
+ 1, sizeof(*argv
));
862 // All arguments in command must be strings
863 for (unsigned int i
= 0; i
< command_length
; i
++) {
864 PyObject
* item
= PyList_GET_ITEM(command
, i
);
866 if (!PyUnicode_Check(item
)) {
867 PyErr_Format(PyExc_TypeError
, "Item %u in command is not a string", i
);
872 argv
[i
] = PyUnicode_AsUTF8(item
);
875 // Check if bind is a sequence
876 if (bind
&& !PySequence_Check(bind
)) {
877 PyErr_SetString(PyExc_ValueError
, "bind is not a sequence");
882 if (callback
&& !PyCallable_Check(callback
)) {
883 PyErr_SetString(PyExc_TypeError
, "callback must be callable\n");
888 r
= pakfire_jail_create(&jail
, self
->pakfire
, flags
);
890 PyErr_SetFromErrno(PyExc_OSError
);
895 if (callback
&& !PyCallable_Check(callback
)) {
896 PyErr_SetString(PyExc_TypeError
, "callback must be callable\n");
902 r
= pakfire_jail_nice(jail
, nice
);
904 PyErr_SetFromErrno(PyExc_OSError
);
909 PyObject
* key
= NULL
;
910 PyObject
* value
= NULL
;
913 // Parse the environment
915 // Check if environ is a dictionary
916 if (!PyDict_Check(environ
)) {
917 PyErr_SetString(PyExc_TypeError
, "environ must be a dictionary");
921 // All keys and values must be strings
922 while (PyDict_Next(environ
, &p
, &key
, &value
)) {
923 if (!PyUnicode_Check(key
) || !PyUnicode_Check(value
)) {
924 PyErr_SetString(PyExc_TypeError
, "Environment contains a non-string object");
928 // Set environment value
929 r
= pakfire_jail_set_env(jail
, PyUnicode_AsUTF8(key
), PyUnicode_AsUTF8(value
));
931 PyErr_SetFromErrno(PyExc_OSError
);
937 const Py_ssize_t num_bind
= PySequence_Length(bind
);
940 for (unsigned int i
= 0; i
< num_bind
; i
++) {
941 PyObject
* b
= PySequence_ITEM(bind
, i
);
945 // Check if this is a Unicode object
946 if (!PyUnicode_Check(b
)) {
947 PyErr_SetString(PyExc_ValueError
, "bind contains a non-Unicode object");
952 const char* path
= PyUnicode_AsUTF8(b
);
955 r
= pakfire_jail_bind(jail
, path
, path
, 0);
957 PyErr_SetFromErrno(PyExc_OSError
);
966 r
= pakfire_jail_exec_communicate(jail
, argv
,
967 NULL
, Pakfire_execute_output_callback
, callback
);
969 // If the return code was negative, we had some internal error
971 PyErr_SetFromErrno(PyExc_OSError
);
974 // Otherwise the executed command returned some error code
976 PyObject
* code
= PyLong_FromLong(r
);
978 // Raise CommandExecutionError
979 PyErr_SetObject(PyExc_CommandExecutionError
, code
);
985 // The process has exited successfully
995 pakfire_jail_unref(jail
);
1000 static PyObject
* Pakfire_dist(PakfireObject
* self
, PyObject
* args
) {
1001 const char* path
= NULL
;
1002 const char* target
= NULL
;
1003 char* result
= NULL
;
1005 if (!PyArg_ParseTuple(args
, "s|z", &path
, &target
))
1008 int r
= pakfire_dist(self
->pakfire
, path
, target
, &result
);
1010 PyErr_SetFromErrno(PyExc_OSError
);
1014 PyObject
* ret
= PyUnicode_FromString(result
);
1020 static PyObject
* Pakfire_copy_in(PakfireObject
* self
, PyObject
* args
) {
1021 const char* src
= NULL
;
1022 const char* dst
= NULL
;
1024 if (!PyArg_ParseTuple(args
, "ss", &src
, &dst
))
1027 int r
= pakfire_copy_in(self
->pakfire
, src
, dst
);
1029 PyErr_SetFromErrno(PyExc_OSError
);
1036 static PyObject
* Pakfire_copy_out(PakfireObject
* self
, PyObject
* args
) {
1037 const char* src
= NULL
;
1038 const char* dst
= NULL
;
1040 if (!PyArg_ParseTuple(args
, "ss", &src
, &dst
))
1043 int r
= pakfire_copy_out(self
->pakfire
, src
, dst
);
1045 PyErr_SetFromErrno(PyExc_OSError
);
1052 static PyObject
* Pakfire_get_repos(PakfireObject
* self
) {
1053 struct pakfire_repolist
* repos
= pakfire_get_repos(self
->pakfire
);
1055 PyErr_SetFromErrno(PyExc_OSError
);
1059 const size_t l
= pakfire_repolist_size(repos
);
1061 PyObject
* list
= PyList_New(l
);
1065 for (unsigned int i
= 0; i
< l
; i
++) {
1066 struct pakfire_repo
* repo
= pakfire_repolist_get(repos
, i
);
1070 PyObject
* obj
= new_repo(&RepoType
, repo
);
1071 PyList_SET_ITEM(list
, i
, obj
);
1073 pakfire_repo_unref(repo
);
1077 pakfire_repolist_unref(repos
);
1082 static PyObject
* execute_return_value(int r
) {
1083 // Raise an OS error if r < 0
1087 PyErr_SetFromErrno(PyExc_OSError
);
1090 // Raise exception when the command failed
1092 PyObject
* code
= PyLong_FromLong(r
);
1094 PyErr_SetObject(PyExc_CommandExecutionError
, code
);
1103 static PyObject
* Pakfire_build(PakfireObject
* self
, PyObject
* args
, PyObject
* kwargs
) {
1115 const char* path
= NULL
;
1116 const char* target
= NULL
;
1117 const char* build_id
= NULL
;
1118 int interactive
= 0;
1119 int disable_snapshot
= 0;
1120 int disable_ccache
= 0;
1121 int disable_tests
= 0;
1123 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "s|zzpppp", kwlist
, &path
, &target
,
1124 &build_id
, &interactive
, &disable_snapshot
, &disable_ccache
, &disable_tests
))
1130 flags
|= PAKFIRE_BUILD_INTERACTIVE
;
1132 // Disable snapshot if requested
1133 if (disable_snapshot
)
1134 flags
|= PAKFIRE_BUILD_DISABLE_SNAPSHOT
;
1136 // Disable ccache if requested
1138 flags
|= PAKFIRE_BUILD_DISABLE_CCACHE
;
1140 // Disable tests if requested
1142 flags
|= PAKFIRE_BUILD_DISABLE_TESTS
;
1145 int r
= pakfire_build(self
->pakfire
, path
, target
, build_id
, flags
);
1147 return execute_return_value(r
);
1150 static PyObject
* Pakfire_shell(PakfireObject
* self
, PyObject
* args
, PyObject
* kwargs
) {
1156 char** packages
= NULL
;
1157 int disable_snapshot
= 0;
1160 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|O&p", kwlist
,
1161 convert_packages
, &packages
, &disable_snapshot
))
1166 if (disable_snapshot
)
1167 flags
|= PAKFIRE_BUILD_DISABLE_SNAPSHOT
;
1169 int r
= pakfire_shell(self
->pakfire
, (const char**)packages
, flags
);
1171 return execute_return_value(r
);
1174 static PyObject
* Pakfire_clean(PakfireObject
* self
) {
1175 int r
= pakfire_clean(self
->pakfire
, 0);
1177 PyErr_SetFromErrno(PyExc_OSError
);
1184 static PyObject
* Pakfire_refresh(PakfireObject
* self
, PyObject
* args
) {
1187 if (!PyArg_ParseTuple(args
, "|p", &force
))
1190 int r
= pakfire_refresh(self
->pakfire
, force
);
1192 PyErr_SetFromErrno(PyExc_OSError
);
1199 static PyObject
* Pakfire_check(PakfireObject
* self
) {
1200 struct pakfire_filelist
* errors
= NULL
;
1203 // Allocate a filelist for errors
1204 r
= pakfire_filelist_create(&errors
, self
->pakfire
);
1209 r
= pakfire_check(self
->pakfire
, errors
);
1213 const size_t num_errors
= pakfire_filelist_size(errors
);
1215 // Did we find any errors?
1217 PyObject
* _errors
= PyList_FromFileList(errors
);
1221 pakfire_filelist_unref(errors
);
1223 // Raise CheckFileVerificationError
1224 PyErr_SetObject(PyExc_CheckFileVerificationError
, _errors
);
1229 pakfire_filelist_unref(errors
);
1235 pakfire_filelist_unref(errors
);
1237 // Raise exception from errno
1238 PyErr_SetFromErrno(PyExc_OSError
);
1242 static PyObject
* Pakfire_sync(PakfireObject
* self
, PyObject
* args
, PyObject
* kwargs
) {
1248 int keep_orphaned
= 0;
1250 PyObject
* status_callback
= NULL
;
1252 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|$pO", kwlist
,
1253 &keep_orphaned
, &status_callback
))
1257 flags
|= PAKFIRE_REQUEST_KEEP_ORPHANED
;
1259 int r
= pakfire_sync(self
->pakfire
, 0, flags
, NULL
,
1260 Pakfire_status_callback
, status_callback
);
1262 PyErr_SetFromErrno(PyExc_OSError
);
1269 static PyObject
* Pakfire_open(PakfireObject
* self
, PyObject
* args
) {
1270 struct pakfire_archive
* archive
= NULL
;
1271 const char* path
= NULL
;
1273 if (!PyArg_ParseTuple(args
, "s", &path
))
1276 int r
= pakfire_archive_open(&archive
, self
->pakfire
, path
);
1278 PyErr_SetFromErrno(PyExc_OSError
);
1282 // Create Python object
1283 PyObject
* object
= new_archive(&ArchiveType
, archive
);
1284 pakfire_archive_unref(archive
);
1289 static PyObject
* Pakfire_repo_compose(PakfireObject
* self
, PyObject
* args
, PyObject
* kwargs
) {
1290 char* kwlist
[] = { "path", "files", NULL
};
1291 const char* path
= NULL
;
1292 PyObject
* list
= NULL
;
1294 PyObject
* ret
= NULL
;
1296 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "sO", kwlist
, &path
, &list
))
1299 // List must be a sequence
1300 if (!PySequence_Check(list
)) {
1301 PyErr_SetString(PyExc_ValueError
, "Expected a sequence.");
1305 const int flags
= 0;
1307 // How many new files do we have?
1308 ssize_t num_files
= PySequence_Length(list
);
1312 // Allocate files array
1313 const char** files
= calloc(num_files
+ 1, sizeof(*files
));
1315 PyErr_SetFromErrno(PyExc_OSError
);
1319 for (int i
= 0; i
< num_files
; i
++) {
1320 PyObject
* file
= PySequence_GetItem(list
, i
);
1324 // Check if file is a Unicode object
1325 if (!PyUnicode_Check(file
)) {
1326 PyErr_SetString(PyExc_ValueError
, "Expected a string.");
1330 // Add pointer to string to files array
1331 files
[i
] = PyUnicode_AsUTF8(file
);
1338 int r
= pakfire_repo_compose(self
->pakfire
, path
, flags
, files
);
1340 PyErr_SetFromErrno(PyExc_OSError
);
1344 // Return None on success
1355 static struct PyMethodDef Pakfire_methods
[] = {
1358 (PyCFunction
)Pakfire_build
,
1359 METH_VARARGS
|METH_KEYWORDS
,
1364 (PyCFunction
)Pakfire_check
,
1370 (PyCFunction
)Pakfire_clean
,
1376 (PyCFunction
)Pakfire_copy_in
,
1382 (PyCFunction
)Pakfire_copy_out
,
1388 (PyCFunction
)Pakfire_dist
,
1394 (PyCFunction
)Pakfire_erase
,
1395 METH_VARARGS
|METH_KEYWORDS
,
1400 (PyCFunction
)Pakfire_execute
,
1401 METH_VARARGS
|METH_KEYWORDS
,
1406 (PyCFunction
)Pakfire_fetch_key
,
1407 METH_VARARGS
|METH_KEYWORDS
,
1412 (PyCFunction
)Pakfire_generate_key
,
1413 METH_VARARGS
|METH_KEYWORDS
,
1418 (PyCFunction
)Pakfire_get_key
,
1424 (PyCFunction
)Pakfire_get_repo
,
1430 (PyCFunction
)Pakfire_import_key
,
1436 (PyCFunction
)Pakfire_install
,
1437 METH_VARARGS
|METH_KEYWORDS
,
1442 (PyCFunction
)Pakfire_open
,
1448 (PyCFunction
)Pakfire_refresh
,
1454 (PyCFunction
)Pakfire_repo_compose
,
1455 METH_VARARGS
|METH_KEYWORDS
,
1460 (PyCFunction
)Pakfire_search
,
1461 METH_VARARGS
|METH_KEYWORDS
,
1466 (PyCFunction
)Pakfire_shell
,
1467 METH_VARARGS
|METH_KEYWORDS
,
1472 (PyCFunction
)Pakfire_sync
,
1473 METH_VARARGS
|METH_KEYWORDS
,
1478 (PyCFunction
)Pakfire_update
,
1479 METH_VARARGS
|METH_KEYWORDS
,
1484 (PyCFunction
)Pakfire_version_compare
,
1490 (PyCFunction
)Pakfire_whatprovides
,
1496 (PyCFunction
)Pakfire_whatrequires
,
1503 static struct PyGetSetDef Pakfire_getsetters
[] = {
1506 (getter
)Pakfire_get_arch
,
1513 (getter
)Pakfire_get_keys
,
1520 (getter
)Pakfire_get_path
,
1527 (getter
)Pakfire_get_repos
,
1535 PyTypeObject PakfireType
= {
1536 PyVarObject_HEAD_INIT(NULL
, 0)
1537 tp_name
: "_pakfire.Pakfire",
1538 tp_basicsize
: sizeof(PakfireObject
),
1539 tp_flags
: Py_TPFLAGS_DEFAULT
|Py_TPFLAGS_BASETYPE
,
1540 tp_new
: Pakfire_new
,
1541 tp_dealloc
: (destructor
)Pakfire_dealloc
,
1542 tp_init
: (initproc
)Pakfire_init
,
1543 tp_doc
: "Pakfire object",
1544 tp_methods
: Pakfire_methods
,
1545 tp_getset
: Pakfire_getsetters
,
1546 tp_repr
: (reprfunc
)Pakfire_repr
,