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_logging_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
) {
828 struct pakfire_jail
* jail
= NULL
;
829 const char** argv
= NULL
;
832 PyObject
* ret
= NULL
;
835 PyObject
* command
= NULL
;
836 PyObject
* environ
= NULL
;
837 PyObject
* bind
= NULL
;
838 PyObject
* logging_callback
= NULL
;
840 int return_output
= 0;
842 if (!PyArg_ParseTupleAndKeywords(args
, kwds
, "O|OOOip", kwlist
, &command
, &environ
,
843 &bind
, &logging_callback
, &nice
, &return_output
))
846 // Check if command is a list
847 if (!PyList_Check(command
)) {
848 PyErr_SetString(PyExc_TypeError
, "command must be a list");
852 const ssize_t command_length
= PyList_Size(command
);
854 // Check if command is not empty
855 if (command_length
== 0) {
856 PyErr_SetString(PyExc_ValueError
, "command is empty");
861 argv
= calloc(command_length
+ 1, sizeof(*argv
));
865 // All arguments in command must be strings
866 for (unsigned int i
= 0; i
< command_length
; i
++) {
867 PyObject
* item
= PyList_GET_ITEM(command
, i
);
869 if (!PyUnicode_Check(item
)) {
870 PyErr_Format(PyExc_TypeError
, "Item %u in command is not a string", i
);
875 argv
[i
] = PyUnicode_AsUTF8(item
);
878 // Check if bind is a sequence
879 if (bind
&& !PySequence_Check(bind
)) {
880 PyErr_SetString(PyExc_ValueError
, "bind is not a sequence");
885 r
= pakfire_jail_create(&jail
, self
->pakfire
, flags
);
887 PyErr_SetFromErrno(PyExc_OSError
);
891 // Set logging callback
892 if (logging_callback
) {
893 if (!PyCallable_Check(logging_callback
)) {
894 PyErr_SetString(PyExc_TypeError
, "logging_callback must be callable\n");
898 pakfire_jail_set_log_callback(jail
, __Pakfire_logging_callback
, logging_callback
);
903 r
= pakfire_jail_nice(jail
, nice
);
905 PyErr_SetFromErrno(PyExc_OSError
);
910 PyObject
* key
= NULL
;
911 PyObject
* value
= NULL
;
914 // Parse the environment
916 // Check if environ is a dictionary
917 if (!PyDict_Check(environ
)) {
918 PyErr_SetString(PyExc_TypeError
, "environ must be a dictionary");
922 // All keys and values must be strings
923 while (PyDict_Next(environ
, &p
, &key
, &value
)) {
924 if (!PyUnicode_Check(key
) || !PyUnicode_Check(value
)) {
925 PyErr_SetString(PyExc_TypeError
, "Environment contains a non-string object");
929 // Set environment value
930 r
= pakfire_jail_set_env(jail
, PyUnicode_AsUTF8(key
), PyUnicode_AsUTF8(value
));
932 PyErr_SetFromErrno(PyExc_OSError
);
938 const Py_ssize_t num_bind
= PySequence_Length(bind
);
941 for (unsigned int i
= 0; i
< num_bind
; i
++) {
942 PyObject
* b
= PySequence_ITEM(bind
, i
);
946 // Check if this is a Unicode object
947 if (!PyUnicode_Check(b
)) {
948 PyErr_SetString(PyExc_ValueError
, "bind contains a non-Unicode object");
953 const char* path
= PyUnicode_AsUTF8(b
);
956 r
= pakfire_jail_bind(jail
, path
, path
, 0);
958 PyErr_SetFromErrno(PyExc_OSError
);
967 r
= pakfire_jail_exec(jail
, argv
, (return_output
) ? &output
: NULL
);
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
987 // Did the user request the output?
989 // Return the buffer as bytes
991 ret
= PyBytes_FromString(output
);
994 // Otherwise just return None
1007 // Dereference the logging callback
1008 // It might happen that the jail is not being freed because something else is
1009 // holding a reference to it. We will however lose the reference to the logging
1010 // function here which is why we reset it.
1011 pakfire_jail_set_log_callback(jail
, NULL
, NULL
);
1013 pakfire_jail_unref(jail
);
1019 static PyObject
* Pakfire_dist(PakfireObject
* self
, PyObject
* args
) {
1020 const char* path
= NULL
;
1021 const char* target
= NULL
;
1022 char* result
= NULL
;
1024 if (!PyArg_ParseTuple(args
, "s|z", &path
, &target
))
1027 int r
= pakfire_dist(self
->pakfire
, path
, target
, &result
);
1029 PyErr_SetFromErrno(PyExc_OSError
);
1033 PyObject
* ret
= PyUnicode_FromString(result
);
1039 static PyObject
* Pakfire_copy_in(PakfireObject
* self
, PyObject
* args
) {
1040 const char* src
= NULL
;
1041 const char* dst
= NULL
;
1043 if (!PyArg_ParseTuple(args
, "ss", &src
, &dst
))
1046 int r
= pakfire_copy_in(self
->pakfire
, src
, dst
);
1048 PyErr_SetFromErrno(PyExc_OSError
);
1055 static PyObject
* Pakfire_copy_out(PakfireObject
* self
, PyObject
* args
) {
1056 const char* src
= NULL
;
1057 const char* dst
= NULL
;
1059 if (!PyArg_ParseTuple(args
, "ss", &src
, &dst
))
1062 int r
= pakfire_copy_out(self
->pakfire
, src
, dst
);
1064 PyErr_SetFromErrno(PyExc_OSError
);
1071 static PyObject
* Pakfire_get_repos(PakfireObject
* self
) {
1072 struct pakfire_repolist
* repos
= pakfire_get_repos(self
->pakfire
);
1074 PyErr_SetFromErrno(PyExc_OSError
);
1078 const size_t l
= pakfire_repolist_size(repos
);
1080 PyObject
* list
= PyList_New(l
);
1084 for (unsigned int i
= 0; i
< l
; i
++) {
1085 struct pakfire_repo
* repo
= pakfire_repolist_get(repos
, i
);
1089 PyObject
* obj
= new_repo(&RepoType
, repo
);
1090 PyList_SET_ITEM(list
, i
, obj
);
1092 pakfire_repo_unref(repo
);
1096 pakfire_repolist_unref(repos
);
1101 static PyObject
* execute_return_value(int r
) {
1102 // Raise an OS error if r < 0
1106 PyErr_SetFromErrno(PyExc_OSError
);
1109 // Raise exception when the command failed
1111 PyObject
* code
= PyLong_FromLong(r
);
1113 PyErr_SetObject(PyExc_CommandExecutionError
, code
);
1122 static PyObject
* Pakfire_build(PakfireObject
* self
, PyObject
* args
, PyObject
* kwargs
) {
1134 const char* path
= NULL
;
1135 const char* target
= NULL
;
1136 const char* build_id
= NULL
;
1137 int interactive
= 0;
1138 int disable_snapshot
= 0;
1139 int disable_ccache
= 0;
1140 int disable_tests
= 0;
1142 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "s|zzpppp", kwlist
, &path
, &target
,
1143 &build_id
, &interactive
, &disable_snapshot
, &disable_ccache
, &disable_tests
))
1149 flags
|= PAKFIRE_BUILD_INTERACTIVE
;
1151 // Disable snapshot if requested
1152 if (disable_snapshot
)
1153 flags
|= PAKFIRE_BUILD_DISABLE_SNAPSHOT
;
1155 // Disable ccache if requested
1157 flags
|= PAKFIRE_BUILD_DISABLE_CCACHE
;
1159 // Disable tests if requested
1161 flags
|= PAKFIRE_BUILD_DISABLE_TESTS
;
1164 int r
= pakfire_build(self
->pakfire
, path
, target
, build_id
, flags
);
1166 return execute_return_value(r
);
1169 static PyObject
* Pakfire_shell(PakfireObject
* self
, PyObject
* args
, PyObject
* kwargs
) {
1175 char** packages
= NULL
;
1176 int disable_snapshot
= 0;
1179 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|O&p", kwlist
,
1180 convert_packages
, &packages
, &disable_snapshot
))
1185 if (disable_snapshot
)
1186 flags
|= PAKFIRE_BUILD_DISABLE_SNAPSHOT
;
1188 int r
= pakfire_shell(self
->pakfire
, (const char**)packages
, flags
);
1190 return execute_return_value(r
);
1193 static PyObject
* Pakfire_clean(PakfireObject
* self
) {
1194 int r
= pakfire_clean(self
->pakfire
, 0);
1196 PyErr_SetFromErrno(PyExc_OSError
);
1203 static PyObject
* Pakfire_refresh(PakfireObject
* self
, PyObject
* args
) {
1206 if (!PyArg_ParseTuple(args
, "|p", &force
))
1209 int r
= pakfire_refresh(self
->pakfire
, force
);
1211 PyErr_SetFromErrno(PyExc_OSError
);
1218 static PyObject
* Pakfire_check(PakfireObject
* self
) {
1219 struct pakfire_filelist
* errors
= NULL
;
1222 // Allocate a filelist for errors
1223 r
= pakfire_filelist_create(&errors
, self
->pakfire
);
1228 r
= pakfire_check(self
->pakfire
, errors
);
1232 const size_t num_errors
= pakfire_filelist_size(errors
);
1234 // Did we find any errors?
1236 PyObject
* _errors
= PyList_FromFileList(errors
);
1240 pakfire_filelist_unref(errors
);
1242 // Raise CheckFileVerificationError
1243 PyErr_SetObject(PyExc_CheckFileVerificationError
, _errors
);
1248 pakfire_filelist_unref(errors
);
1254 pakfire_filelist_unref(errors
);
1256 // Raise exception from errno
1257 PyErr_SetFromErrno(PyExc_OSError
);
1261 static PyObject
* Pakfire_sync(PakfireObject
* self
, PyObject
* args
, PyObject
* kwargs
) {
1267 int keep_orphaned
= 0;
1269 PyObject
* status_callback
= NULL
;
1271 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|$pO", kwlist
,
1272 &keep_orphaned
, &status_callback
))
1276 flags
|= PAKFIRE_REQUEST_KEEP_ORPHANED
;
1278 int r
= pakfire_sync(self
->pakfire
, 0, flags
, NULL
,
1279 Pakfire_status_callback
, status_callback
);
1281 PyErr_SetFromErrno(PyExc_OSError
);
1288 static PyObject
* Pakfire_open(PakfireObject
* self
, PyObject
* args
) {
1289 struct pakfire_archive
* archive
= NULL
;
1290 const char* path
= NULL
;
1292 if (!PyArg_ParseTuple(args
, "s", &path
))
1295 int r
= pakfire_archive_open(&archive
, self
->pakfire
, path
);
1297 PyErr_SetFromErrno(PyExc_OSError
);
1301 // Create Python object
1302 PyObject
* object
= new_archive(&ArchiveType
, archive
);
1303 pakfire_archive_unref(archive
);
1308 static PyObject
* Pakfire_repo_compose(PakfireObject
* self
, PyObject
* args
, PyObject
* kwargs
) {
1309 char* kwlist
[] = { "path", "files", NULL
};
1310 const char* path
= NULL
;
1311 PyObject
* list
= NULL
;
1313 PyObject
* ret
= NULL
;
1315 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "sO", kwlist
, &path
, &list
))
1318 // List must be a sequence
1319 if (!PySequence_Check(list
)) {
1320 PyErr_SetString(PyExc_ValueError
, "Expected a sequence.");
1324 const int flags
= 0;
1326 // How many new files do we have?
1327 ssize_t num_files
= PySequence_Length(list
);
1331 // Allocate files array
1332 const char** files
= calloc(num_files
+ 1, sizeof(*files
));
1334 PyErr_SetFromErrno(PyExc_OSError
);
1338 for (int i
= 0; i
< num_files
; i
++) {
1339 PyObject
* file
= PySequence_GetItem(list
, i
);
1343 // Check if file is a Unicode object
1344 if (!PyUnicode_Check(file
)) {
1345 PyErr_SetString(PyExc_ValueError
, "Expected a string.");
1349 // Add pointer to string to files array
1350 files
[i
] = PyUnicode_AsUTF8(file
);
1357 int r
= pakfire_repo_compose(self
->pakfire
, path
, flags
, files
);
1359 PyErr_SetFromErrno(PyExc_OSError
);
1363 // Return None on success
1374 static struct PyMethodDef Pakfire_methods
[] = {
1377 (PyCFunction
)Pakfire_build
,
1378 METH_VARARGS
|METH_KEYWORDS
,
1383 (PyCFunction
)Pakfire_check
,
1389 (PyCFunction
)Pakfire_clean
,
1395 (PyCFunction
)Pakfire_copy_in
,
1401 (PyCFunction
)Pakfire_copy_out
,
1407 (PyCFunction
)Pakfire_dist
,
1413 (PyCFunction
)Pakfire_erase
,
1414 METH_VARARGS
|METH_KEYWORDS
,
1419 (PyCFunction
)Pakfire_execute
,
1420 METH_VARARGS
|METH_KEYWORDS
,
1425 (PyCFunction
)Pakfire_fetch_key
,
1426 METH_VARARGS
|METH_KEYWORDS
,
1431 (PyCFunction
)Pakfire_generate_key
,
1432 METH_VARARGS
|METH_KEYWORDS
,
1437 (PyCFunction
)Pakfire_get_key
,
1443 (PyCFunction
)Pakfire_get_repo
,
1449 (PyCFunction
)Pakfire_import_key
,
1455 (PyCFunction
)Pakfire_install
,
1456 METH_VARARGS
|METH_KEYWORDS
,
1461 (PyCFunction
)Pakfire_open
,
1467 (PyCFunction
)Pakfire_refresh
,
1473 (PyCFunction
)Pakfire_repo_compose
,
1474 METH_VARARGS
|METH_KEYWORDS
,
1479 (PyCFunction
)Pakfire_search
,
1480 METH_VARARGS
|METH_KEYWORDS
,
1485 (PyCFunction
)Pakfire_shell
,
1486 METH_VARARGS
|METH_KEYWORDS
,
1491 (PyCFunction
)Pakfire_sync
,
1492 METH_VARARGS
|METH_KEYWORDS
,
1497 (PyCFunction
)Pakfire_update
,
1498 METH_VARARGS
|METH_KEYWORDS
,
1503 (PyCFunction
)Pakfire_version_compare
,
1509 (PyCFunction
)Pakfire_whatprovides
,
1515 (PyCFunction
)Pakfire_whatrequires
,
1522 static struct PyGetSetDef Pakfire_getsetters
[] = {
1525 (getter
)Pakfire_get_arch
,
1532 (getter
)Pakfire_get_keys
,
1539 (getter
)Pakfire_get_path
,
1546 (getter
)Pakfire_get_repos
,
1554 PyTypeObject PakfireType
= {
1555 PyVarObject_HEAD_INIT(NULL
, 0)
1556 tp_name
: "_pakfire.Pakfire",
1557 tp_basicsize
: sizeof(PakfireObject
),
1558 tp_flags
: Py_TPFLAGS_DEFAULT
|Py_TPFLAGS_BASETYPE
,
1559 tp_new
: Pakfire_new
,
1560 tp_dealloc
: (destructor
)Pakfire_dealloc
,
1561 tp_init
: (initproc
)Pakfire_init
,
1562 tp_doc
: "Pakfire object",
1563 tp_methods
: Pakfire_methods
,
1564 tp_getset
: Pakfire_getsetters
,
1565 tp_repr
: (reprfunc
)Pakfire_repr
,