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
;
64 // Do nothing if callback isn't set
68 // Translate priority to Python logging priorities
82 // Drop messages of an unknown priority
87 PyObject
* tuple
= NULL
;
88 PyObject
* result
= NULL
;
92 int r
= vasprintf(&buffer
, format
, args
);
96 // Build a tuple with the priority and the log message
97 tuple
= Py_BuildValue("(is)", priority
, buffer
);
102 result
= PyObject_CallObject(callback
, tuple
);
111 static int Pakfire_confirm_callback(struct pakfire
* pakfire
, void* data
,
112 const char* message
, const char* question
) {
113 PyObject
* callback
= (PyObject
*)data
;
116 // Do nothing if callback isn't set
120 PyObject
* args
= Py_BuildValue("(ss)", message
, question
);
124 PyObject
* result
= PyObject_CallObject(callback
, args
);
126 // Extract return code
127 if (PyLong_Check(result
))
128 r
= PyLong_AsLong(result
);
136 static int Pakfire_init(PakfireObject
* self
, PyObject
* args
, PyObject
* kwds
) {
148 const char* path
= NULL
;
149 const char* arch
= NULL
;
150 const char* conf
= NULL
;
155 if (!PyArg_ParseTupleAndKeywords(args
, kwds
, "|zzOppzpO", kwlist
,
156 &path
, &arch
, &self
->callbacks
.log
, &interactive
, &offline
, &conf
, &build
,
157 &self
->callbacks
.confirm
))
160 // Check if log callback is callable
161 if (self
->callbacks
.log
&& !PyCallable_Check(self
->callbacks
.log
)) {
162 PyErr_SetString(PyExc_TypeError
, "logger must be callable\n");
166 // Check if confirm callback is callable
167 if (self
->callbacks
.confirm
&& !PyCallable_Check(self
->callbacks
.confirm
)) {
168 PyErr_SetString(PyExc_TypeError
, "Confirm callback is not callable");
174 // Enable interactive mode
176 flags
|= PAKFIRE_FLAGS_INTERACTIVE
;
178 // Enable offline mode
180 flags
|= PAKFIRE_FLAGS_OFFLINE
;
184 flags
|= PAKFIRE_FLAGS_BUILD
;
186 // Configure callbacks
187 if (self
->callbacks
.log
)
188 Py_INCREF(self
->callbacks
.log
);
190 // Create a new Pakfire instance
191 int r
= pakfire_create(&self
->pakfire
, path
, arch
, conf
, flags
,
192 LOG_DEBUG
, Pakfire_log_callback
, self
->callbacks
.log
);
195 // Invalid architecture or path
197 PyErr_SetString(PyExc_ValueError
, "Invalid architecture or path");
202 PyErr_SetFromErrno(PyExc_OSError
);
208 // Configure confirm callback
209 if (self
->callbacks
.confirm
) {
210 pakfire_set_confirm_callback(self
->pakfire
,
211 Pakfire_confirm_callback
, self
->callbacks
.confirm
);
213 Py_INCREF(self
->callbacks
.confirm
);
219 static void Pakfire_dealloc(PakfireObject
* self
) {
221 // Reset log callback
222 if (self
->callbacks
.log
) {
223 pakfire_set_log_callback(self
->pakfire
, NULL
, NULL
);
224 Py_DECREF(self
->callbacks
.log
);
227 // Reset confirm callback
228 if (self
->callbacks
.confirm
) {
229 pakfire_set_confirm_callback(self
->pakfire
, NULL
, NULL
);
230 Py_DECREF(self
->callbacks
.confirm
);
233 pakfire_unref(self
->pakfire
);
236 Py_TYPE(self
)->tp_free((PyObject
*)self
);
239 static PyObject
* Pakfire_repr(PakfireObject
* self
) {
240 const char* path
= pakfire_get_path(self
->pakfire
);
241 const char* arch
= pakfire_get_arch(self
->pakfire
);
243 return PyUnicode_FromFormat("<_pakfire.Pakfire %s (%s)>", path
, arch
);
246 static PyObject
* Pakfire_get_path(PakfireObject
* self
) {
247 const char* path
= pakfire_get_path(self
->pakfire
);
249 return PyUnicode_FromString(path
);
252 static PyObject
* Pakfire_get_arch(PakfireObject
* self
) {
253 const char* arch
= pakfire_get_arch(self
->pakfire
);
255 return PyUnicode_FromString(arch
);
258 static PyObject
* Pakfire_get_repo(PakfireObject
* self
, PyObject
* args
) {
259 const char* name
= NULL
;
261 if (!PyArg_ParseTuple(args
, "s", &name
))
264 struct pakfire_repo
* repo
= pakfire_get_repo(self
->pakfire
, name
);
268 PyObject
* obj
= new_repo(&RepoType
, repo
);
269 pakfire_repo_unref(repo
);
274 static void Pakfire_status_callback(struct pakfire
* pakfire
, void* data
,
275 int progress
, const char* status
) {
276 PyObject
* callback
= (PyObject
*)data
;
278 // Do not attempt to call nothing
283 PyObject
* args
= Py_BuildValue("(is)", progress
, status
);
288 PyObject
* result
= PyObject_CallObject(callback
, args
);
294 static int convert_packages(PyObject
* object
, void* address
) {
295 char*** packages
= (char***)address
;
297 // Called for cleanup
301 // Nothing to do when object is None
302 if (object
== Py_None
)
303 return Py_CLEANUP_SUPPORTED
;
305 if (!PySequence_Check(object
)) {
306 PyErr_SetString(PyExc_ValueError
, "Packages must be a sequence");
310 const unsigned int length
= PySequence_Length(object
);
312 return Py_CLEANUP_SUPPORTED
;
315 *packages
= calloc(length
+ 1, sizeof(*packages
));
317 PyErr_SetFromErrno(PyExc_OSError
);
321 for (unsigned int i
= 0; i
< length
; i
++) {
322 PyObject
* item
= PySequence_GetItem(object
, i
);
324 // Check if input is a string
325 if (!PyUnicode_Check(item
)) {
328 PyErr_SetString(PyExc_AttributeError
, "Expected a string");
333 const char* package
= PyUnicode_AsUTF8(item
);
339 // Add package to array
340 (*packages
)[i
] = strdup(package
);
341 if (!(*packages
)[i
]) {
350 return Py_CLEANUP_SUPPORTED
;
354 for (char** package
= *packages
; *package
; package
++)
362 static PyObject
* Pakfire_install(PakfireObject
* self
, PyObject
* args
, PyObject
* kwargs
) {
366 "without_recommended",
372 char** packages
= NULL
;
374 int without_recommended
= 0;
375 int allow_uninstall
= 0;
376 int allow_downgrade
= 0;
377 int solver_flags
= 0;
378 int transaction_flags
= 0;
379 PyObject
* status_callback
= NULL
;
381 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "O&|$ppppO", kwlist
,
382 convert_packages
, &packages
, &dryrun
, &without_recommended
, &allow_uninstall
,
383 &allow_downgrade
, &status_callback
))
386 // Check if callback is callable
387 if (status_callback
&& !PyCallable_Check(status_callback
)) {
388 PyErr_SetString(PyExc_TypeError
, "status_callback must be callable");
392 // Enable dry-run mode
394 transaction_flags
|= PAKFIRE_TRANSACTION_DRY_RUN
;
396 // Do not install recommended packages
397 if (without_recommended
)
398 solver_flags
|= PAKFIRE_REQUEST_WITHOUT_RECOMMENDED
;
400 // Can the solver uninstall packages?
402 solver_flags
|= PAKFIRE_REQUEST_ALLOW_UNINSTALL
;
404 // Can the solver downgrade packages?
406 solver_flags
|= PAKFIRE_REQUEST_ALLOW_DOWNGRADE
;
408 // Run pakfire_install
409 int r
= pakfire_install(self
->pakfire
, transaction_flags
, solver_flags
,
410 (const char**)packages
, NULL
, 0, NULL
, Pakfire_status_callback
, status_callback
);
412 PyErr_SetFromErrno(PyExc_OSError
);
415 for (char** package
= packages
; *package
; package
++)
426 static PyObject
* Pakfire_erase(PakfireObject
* self
, PyObject
* args
, PyObject
* kwargs
) {
434 char** packages
= NULL
;
436 int keep_dependencies
= 0;
437 int transaction_flags
= 0;
439 PyObject
* status_callback
= NULL
;
441 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "O&|$ppO", kwlist
,
442 convert_packages
, &packages
, &dryrun
, &keep_dependencies
, &status_callback
))
445 // Check if callback is callable
446 if (status_callback
&& !PyCallable_Check(status_callback
)) {
447 PyErr_SetString(PyExc_TypeError
, "status_callback must be callable");
452 transaction_flags
|= PAKFIRE_TRANSACTION_DRY_RUN
;
454 if (keep_dependencies
)
455 flags
|= PAKFIRE_REQUEST_KEEP_DEPS
;
458 int r
= pakfire_erase(self
->pakfire
, transaction_flags
, 0, (const char**)packages
,
459 NULL
, flags
, NULL
, Pakfire_status_callback
, status_callback
);
461 PyErr_SetFromErrno(PyExc_OSError
);
464 for (char** package
= packages
; *package
; package
++)
475 static PyObject
* Pakfire_update(PakfireObject
* self
, PyObject
* args
, PyObject
* kwargs
) {
485 char** packages
= NULL
;
486 char** excludes
= NULL
;
488 int allow_uninstall
= 0;
489 int allow_downgrade
= 0;
490 int solver_flags
= 0;
491 int transaction_flags
= 0;
492 PyObject
* status_callback
= NULL
;
494 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "O&|$O&ppO", kwlist
,
495 convert_packages
, &packages
, convert_packages
, &excludes
,
496 &allow_uninstall
, &allow_downgrade
, &status_callback
))
499 // Check if callback is callable
500 if (status_callback
&& !PyCallable_Check(status_callback
)) {
501 PyErr_SetString(PyExc_TypeError
, "status_callback must be callable");
506 transaction_flags
= PAKFIRE_TRANSACTION_DRY_RUN
;
508 // Can the solver uninstall packages?
510 solver_flags
|= PAKFIRE_REQUEST_ALLOW_UNINSTALL
;
512 // Can the solver downgrade packages?
514 solver_flags
|= PAKFIRE_REQUEST_ALLOW_DOWNGRADE
;
516 // Run pakfire_update
517 int r
= pakfire_update(self
->pakfire
, transaction_flags
, solver_flags
,
518 (const char**)packages
, (const char**)excludes
, 0, NULL
,
519 Pakfire_status_callback
, status_callback
);
521 PyErr_SetFromErrno(PyExc_OSError
);
524 for (char** package
= packages
; *package
; package
++)
530 for (char** exclude
= excludes
; *exclude
; exclude
++)
541 static PyObject
* Pakfire_keys_to_list(struct pakfire_key
** keys
) {
542 PyObject
* list
= PyList_New(0);
548 // Push all keys onto the list
549 for (struct pakfire_key
** key
= keys
; *key
; key
++) {
550 PyObject
* object
= new_key(&KeyType
, *key
);
554 PyList_Append(list
, object
);
565 static PyObject
* Pakfire_get_keys(PakfireObject
* self
) {
566 struct pakfire_key
** keys
= NULL
;
568 int r
= pakfire_list_keys(self
->pakfire
, &keys
);
570 PyErr_SetFromErrno(PyExc_OSError
);
574 // Convert keys to list
575 PyObject
* list
= Pakfire_keys_to_list(keys
);
579 for (struct pakfire_key
** key
= keys
; *key
; key
++)
580 pakfire_key_unref(*key
);
587 static PyObject
* Pakfire_get_key(PakfireObject
* self
, PyObject
* args
) {
588 const char* pattern
= NULL
;
590 if (!PyArg_ParseTuple(args
, "s", &pattern
))
593 // Try finding the key
594 struct pakfire_key
* key
= pakfire_key_get(self
->pakfire
, pattern
);
598 PyObject
* object
= new_key(&KeyType
, key
);
599 pakfire_key_unref(key
);
604 static PyObject
* Pakfire_generate_key(PakfireObject
* self
, PyObject
* args
, PyObject
* kwds
) {
605 char* kwlist
[] = { "userid", "algorithm", NULL
};
606 struct pakfire_key
* key
= NULL
;
607 const char* userid
= NULL
;
608 const char* algo
= NULL
;
610 if (!PyArg_ParseTupleAndKeywords(args
, kwds
, "s|$z", kwlist
, &userid
, &algo
))
613 // Generate a new key
614 int r
= pakfire_key_generate(&key
, self
->pakfire
, algo
, userid
);
616 PyErr_SetFromErrno(PyExc_OSError
);
620 PyObject
* object
= new_key(&KeyType
, key
);
621 pakfire_key_unref(key
);
626 static PyObject
* Pakfire_import_key(PakfireObject
* self
, PyObject
* args
) {
627 PyObject
* object
= NULL
;
629 if (!PyArg_ParseTuple(args
, "O", &object
))
632 // Get a file descriptor from object
633 int fd
= PyObject_AsFileDescriptor(object
);
638 FILE* f
= fdopen(fd
, "r");
640 PyErr_SetFromErrno(PyExc_OSError
);
644 struct pakfire_key
** keys
= NULL
;
646 // Import keys from f
647 int r
= pakfire_key_import(self
->pakfire
, f
, &keys
);
649 PyErr_SetFromErrno(PyExc_OSError
);
653 // Convert keys to list
654 PyObject
* list
= Pakfire_keys_to_list(keys
);
657 for (struct pakfire_key
** key
= keys
; *key
; key
++)
658 pakfire_key_unref(*key
);
664 static PyObject
* Pakfire_fetch_key(PakfireObject
* self
, PyObject
* args
, PyObject
* kwds
) {
665 char* kwlist
[] = { "userid", "fingerprint", NULL
};
666 struct pakfire_key
* key
= NULL
;
667 const char* userid
= NULL
;
668 const char* fingerprint
= NULL
;
670 if (!PyArg_ParseTupleAndKeywords(args
, kwds
, "|$zz", kwlist
, &userid
, &fingerprint
))
674 int r
= pakfire_key_fetch(&key
, self
->pakfire
, userid
, fingerprint
);
676 PyErr_SetFromErrno(PyExc_OSError
);
682 PyObject
* object
= new_key(&KeyType
, key
);
683 pakfire_key_unref(key
);
691 static PyObject
* Pakfire_whatprovides(PakfireObject
* self
, PyObject
* args
) {
692 const char* provides
= NULL
;
693 struct pakfire_packagelist
* list
= NULL
;
695 if (!PyArg_ParseTuple(args
, "s", &provides
))
698 int r
= pakfire_whatprovides(self
->pakfire
, provides
, 0, &list
);
700 PyErr_SetFromErrno(PyExc_OSError
);
704 PyObject
* obj
= PyList_FromPackageList(list
);
705 pakfire_packagelist_unref(list
);
710 static PyObject
* Pakfire_whatrequires(PakfireObject
* self
, PyObject
* args
) {
711 const char* requires
= NULL
;
712 struct pakfire_packagelist
* list
= NULL
;
714 if (!PyArg_ParseTuple(args
, "s", &requires
))
717 int r
= pakfire_whatrequires(self
->pakfire
, requires
, 0, &list
);
719 PyErr_SetFromErrno(PyExc_OSError
);
723 PyObject
* obj
= PyList_FromPackageList(list
);
724 pakfire_packagelist_unref(list
);
729 static PyObject
* Pakfire_search(PakfireObject
* self
, PyObject
* args
, PyObject
* kwds
) {
730 char* kwlist
[] = { "pattern", "name_only", NULL
};
731 struct pakfire_packagelist
* list
= NULL
;
732 const char* pattern
= NULL
;
736 if (!PyArg_ParseTupleAndKeywords(args
, kwds
, "s|$p", kwlist
, &pattern
, &name_only
))
739 // Search for package names only
741 flags
|= PAKFIRE_SEARCH_NAME_ONLY
;
743 int r
= pakfire_search(self
->pakfire
, pattern
, flags
, &list
);
745 PyErr_SetFromErrno(PyExc_OSError
);
749 PyObject
* obj
= PyList_FromPackageList(list
);
750 pakfire_packagelist_unref(list
);
755 static PyObject
* Pakfire_version_compare(PakfireObject
* self
, PyObject
* args
) {
756 const char* evr1
= NULL
;
757 const char* evr2
= NULL
;
759 if (!PyArg_ParseTuple(args
, "ss", &evr1
, &evr2
))
762 int cmp
= pakfire_version_compare(self
->pakfire
, evr1
, evr2
);
764 return PyLong_FromLong(cmp
);
767 static int __Pakfire_logging_callback(struct pakfire
* pakfire
, void* data
,
768 int priority
, const char* line
, size_t length
) {
769 PyObject
* callback
= (PyObject
*)data
;
772 // Do nothing if callback isn't set
776 // Translate priority to Python logging priorities
787 // Remove the trailing newline
788 if (line
&& line
[length
- 1] == '\n')
791 // Create tuple with arguments for the callback function
792 PyObject
* args
= Py_BuildValue("(is#)", priority
, line
, (Py_ssize_t
)length
);
796 PyObject
* result
= PyObject_CallObject(callback
, args
);
797 if (result
&& PyLong_Check(result
)) {
798 r
= PyLong_AsLong(result
);
807 static PyObject
* Pakfire_execute(PakfireObject
* self
, PyObject
* args
, PyObject
* kwds
) {
819 struct pakfire_jail
* jail
= NULL
;
820 const char** argv
= NULL
;
823 PyObject
* ret
= NULL
;
826 PyObject
* command
= NULL
;
827 PyObject
* environ
= NULL
;
828 PyObject
* bind
= NULL
;
830 PyObject
* logging_callback
= NULL
;
832 int return_output
= 0;
834 if (!PyArg_ParseTupleAndKeywords(args
, kwds
, "O|OOpOip", kwlist
, &command
, &environ
,
835 &bind
, &interactive
, &logging_callback
, &nice
, &return_output
))
838 // Check if command is a list
839 if (!PyList_Check(command
)) {
840 PyErr_SetString(PyExc_TypeError
, "command must be a list");
844 const ssize_t command_length
= PyList_Size(command
);
846 // Check if command is not empty
847 if (command_length
== 0) {
848 PyErr_SetString(PyExc_ValueError
, "command is empty");
853 argv
= calloc(command_length
+ 1, sizeof(*argv
));
857 // All arguments in command must be strings
858 for (unsigned int i
= 0; i
< command_length
; i
++) {
859 PyObject
* item
= PyList_GET_ITEM(command
, i
);
861 if (!PyUnicode_Check(item
)) {
862 PyErr_Format(PyExc_TypeError
, "Item %u in command is not a string", i
);
867 argv
[i
] = PyUnicode_AsUTF8(item
);
870 // Check if bind is a sequence
871 if (bind
&& !PySequence_Check(bind
)) {
872 PyErr_SetString(PyExc_ValueError
, "bind is not a sequence");
878 flags
|= PAKFIRE_JAIL_INTERACTIVE
;
881 r
= pakfire_jail_create(&jail
, self
->pakfire
, flags
);
883 PyErr_SetFromErrno(PyExc_OSError
);
887 // Set logging callback
888 if (logging_callback
) {
889 if (!PyCallable_Check(logging_callback
)) {
890 PyErr_SetString(PyExc_TypeError
, "logging_callback must be callable\n");
894 pakfire_jail_set_log_callback(jail
, __Pakfire_logging_callback
, logging_callback
);
899 r
= pakfire_jail_nice(jail
, nice
);
901 PyErr_SetFromErrno(PyExc_OSError
);
906 PyObject
* key
= NULL
;
907 PyObject
* value
= NULL
;
910 // Parse the environment
912 // Check if environ is a dictionary
913 if (!PyDict_Check(environ
)) {
914 PyErr_SetString(PyExc_TypeError
, "environ must be a dictionary");
918 // All keys and values must be strings
919 while (PyDict_Next(environ
, &p
, &key
, &value
)) {
920 if (!PyUnicode_Check(key
) || !PyUnicode_Check(value
)) {
921 PyErr_SetString(PyExc_TypeError
, "Environment contains a non-string object");
925 // Set environment value
926 r
= pakfire_jail_set_env(jail
, PyUnicode_AsUTF8(key
), PyUnicode_AsUTF8(value
));
928 PyErr_SetFromErrno(PyExc_OSError
);
934 const Py_ssize_t num_bind
= PySequence_Length(bind
);
937 for (unsigned int i
= 0; i
< num_bind
; i
++) {
938 PyObject
* b
= PySequence_ITEM(bind
, i
);
942 // Check if this is a Unicode object
943 if (!PyUnicode_Check(b
)) {
944 PyErr_SetString(PyExc_ValueError
, "bind contains a non-Unicode object");
949 const char* path
= PyUnicode_AsUTF8(b
);
952 r
= pakfire_jail_bind(jail
, path
, path
, 0);
954 PyErr_SetFromErrno(PyExc_OSError
);
963 r
= pakfire_jail_exec(jail
, argv
, (return_output
) ? &output
: NULL
);
965 // If the return code was negative, we had some internal error
967 PyErr_SetFromErrno(PyExc_OSError
);
970 // Otherwise the executed command returned some error code
972 PyObject
* code
= PyLong_FromLong(r
);
974 // Raise CommandExecutionError
975 PyErr_SetObject(PyExc_CommandExecutionError
, code
);
981 // The process has exited successfully
983 // Did the user request the output?
985 // Return the buffer as bytes
986 ret
= PyBytes_FromString(output
);
988 // Otherwise just return None
1001 // Dereference the logging callback
1002 // It might happen that the jail is not being freed because something else is
1003 // holding a reference to it. We will however lose the reference to the logging
1004 // function here which is why we reset it.
1005 pakfire_jail_set_log_callback(jail
, NULL
, NULL
);
1007 pakfire_jail_unref(jail
);
1013 static PyObject
* Pakfire_dist(PakfireObject
* self
, PyObject
* args
) {
1014 const char* path
= NULL
;
1015 const char* target
= NULL
;
1016 char* result
= NULL
;
1018 if (!PyArg_ParseTuple(args
, "s|z", &path
, &target
))
1021 int r
= pakfire_dist(self
->pakfire
, path
, target
, &result
);
1023 PyErr_SetFromErrno(PyExc_OSError
);
1027 PyObject
* ret
= PyUnicode_FromString(result
);
1033 static PyObject
* Pakfire_copy_in(PakfireObject
* self
, PyObject
* args
) {
1034 const char* src
= NULL
;
1035 const char* dst
= NULL
;
1037 if (!PyArg_ParseTuple(args
, "ss", &src
, &dst
))
1040 int r
= pakfire_copy_in(self
->pakfire
, src
, dst
);
1042 PyErr_SetFromErrno(PyExc_OSError
);
1049 static PyObject
* Pakfire_copy_out(PakfireObject
* self
, PyObject
* args
) {
1050 const char* src
= NULL
;
1051 const char* dst
= NULL
;
1053 if (!PyArg_ParseTuple(args
, "ss", &src
, &dst
))
1056 int r
= pakfire_copy_out(self
->pakfire
, src
, dst
);
1058 PyErr_SetFromErrno(PyExc_OSError
);
1065 static PyObject
* Pakfire_get_repos(PakfireObject
* self
) {
1066 struct pakfire_repolist
* repos
= pakfire_get_repos(self
->pakfire
);
1068 PyErr_SetFromErrno(PyExc_OSError
);
1072 const size_t l
= pakfire_repolist_size(repos
);
1074 PyObject
* list
= PyList_New(l
);
1078 for (unsigned int i
= 0; i
< l
; i
++) {
1079 struct pakfire_repo
* repo
= pakfire_repolist_get(repos
, i
);
1083 PyObject
* obj
= new_repo(&RepoType
, repo
);
1084 PyList_SET_ITEM(list
, i
, obj
);
1086 pakfire_repo_unref(repo
);
1090 pakfire_repolist_unref(repos
);
1095 static PyObject
* execute_return_value(int r
) {
1096 // Raise an OS error if r < 0
1100 PyErr_SetFromErrno(PyExc_OSError
);
1103 // Raise exception when the command failed
1105 PyObject
* code
= PyLong_FromLong(r
);
1107 PyErr_SetObject(PyExc_CommandExecutionError
, code
);
1116 static PyObject
* Pakfire_build(PakfireObject
* self
, PyObject
* args
, PyObject
* kwargs
) {
1125 const char* path
= NULL
;
1126 const char* build_id
= NULL
;
1127 int disable_snapshot
= 0;
1128 int disable_ccache
= 0;
1130 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "s|zpp", kwlist
, &path
, &build_id
,
1131 &disable_snapshot
, &disable_ccache
))
1136 // Disable snapshot if requested
1137 if (disable_snapshot
)
1138 flags
|= PAKFIRE_BUILD_DISABLE_SNAPSHOT
;
1140 // Disable ccache if requested
1142 flags
|= PAKFIRE_BUILD_DISABLE_CCACHE
;
1145 int r
= pakfire_build(self
->pakfire
, path
, NULL
, build_id
, flags
);
1147 return execute_return_value(r
);
1150 static PyObject
* Pakfire_shell(PakfireObject
* self
, PyObject
* args
, PyObject
* kwargs
) {
1155 char** packages
= NULL
;
1158 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|O&", kwlist
, convert_packages
, &packages
))
1161 int r
= pakfire_shell(self
->pakfire
, (const char**)packages
);
1163 return execute_return_value(r
);
1166 static PyObject
* Pakfire_clean(PakfireObject
* self
) {
1167 int r
= pakfire_clean(self
->pakfire
, 0);
1169 PyErr_SetFromErrno(PyExc_OSError
);
1176 static PyObject
* Pakfire_refresh(PakfireObject
* self
, PyObject
* args
) {
1179 if (!PyArg_ParseTuple(args
, "|p", &force
))
1182 int r
= pakfire_refresh(self
->pakfire
, force
);
1184 PyErr_SetFromErrno(PyExc_OSError
);
1191 static PyObject
* Pakfire_check(PakfireObject
* self
) {
1192 int r
= pakfire_check(self
->pakfire
);
1194 PyErr_SetFromErrno(PyExc_OSError
);
1201 static PyObject
* Pakfire_sync(PakfireObject
* self
, PyObject
* args
, PyObject
* kwargs
) {
1207 int keep_orphaned
= 0;
1209 PyObject
* status_callback
= NULL
;
1211 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|$pO", kwlist
,
1212 &keep_orphaned
, &status_callback
))
1216 flags
|= PAKFIRE_REQUEST_KEEP_ORPHANED
;
1218 int r
= pakfire_sync(self
->pakfire
, 0, flags
, NULL
,
1219 Pakfire_status_callback
, status_callback
);
1221 PyErr_SetFromErrno(PyExc_OSError
);
1228 static PyObject
* Pakfire_open(PakfireObject
* self
, PyObject
* args
) {
1229 struct pakfire_archive
* archive
= NULL
;
1230 const char* path
= NULL
;
1232 if (!PyArg_ParseTuple(args
, "s", &path
))
1235 int r
= pakfire_archive_open(&archive
, self
->pakfire
, path
);
1237 PyErr_SetFromErrno(PyExc_OSError
);
1241 // Create Python object
1242 PyObject
* object
= new_archive(&ArchiveType
, archive
);
1243 pakfire_archive_unref(archive
);
1248 static PyObject
* Pakfire_repo_compose(PakfireObject
* self
, PyObject
* args
, PyObject
* kwargs
) {
1249 char* kwlist
[] = { "path", "files", NULL
};
1250 const char* path
= NULL
;
1251 PyObject
* list
= NULL
;
1253 PyObject
* ret
= NULL
;
1255 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "sO", kwlist
, &path
, &list
))
1258 // List must be a sequence
1259 if (!PySequence_Check(list
)) {
1260 PyErr_SetString(PyExc_ValueError
, "Expected a sequence.");
1264 const int flags
= 0;
1266 // How many new files do we have?
1267 ssize_t num_files
= PySequence_Length(list
);
1271 // Allocate files array
1272 const char** files
= calloc(num_files
+ 1, sizeof(*files
));
1274 PyErr_SetFromErrno(PyExc_OSError
);
1278 for (int i
= 0; i
< num_files
; i
++) {
1279 PyObject
* file
= PySequence_GetItem(list
, i
);
1283 // Check if file is a Unicode object
1284 if (!PyUnicode_Check(file
)) {
1285 PyErr_SetString(PyExc_ValueError
, "Expected a string.");
1289 // Add pointer to string to files array
1290 files
[i
] = PyUnicode_AsUTF8(file
);
1297 int r
= pakfire_repo_compose(self
->pakfire
, path
, flags
, files
);
1299 PyErr_SetFromErrno(PyExc_OSError
);
1303 // Return None on success
1314 static struct PyMethodDef Pakfire_methods
[] = {
1317 (PyCFunction
)Pakfire_build
,
1318 METH_VARARGS
|METH_KEYWORDS
,
1323 (PyCFunction
)Pakfire_check
,
1329 (PyCFunction
)Pakfire_clean
,
1335 (PyCFunction
)Pakfire_copy_in
,
1341 (PyCFunction
)Pakfire_copy_out
,
1347 (PyCFunction
)Pakfire_dist
,
1353 (PyCFunction
)Pakfire_erase
,
1354 METH_VARARGS
|METH_KEYWORDS
,
1359 (PyCFunction
)Pakfire_execute
,
1360 METH_VARARGS
|METH_KEYWORDS
,
1365 (PyCFunction
)Pakfire_fetch_key
,
1366 METH_VARARGS
|METH_KEYWORDS
,
1371 (PyCFunction
)Pakfire_generate_key
,
1372 METH_VARARGS
|METH_KEYWORDS
,
1377 (PyCFunction
)Pakfire_get_key
,
1383 (PyCFunction
)Pakfire_get_repo
,
1389 (PyCFunction
)Pakfire_import_key
,
1395 (PyCFunction
)Pakfire_install
,
1396 METH_VARARGS
|METH_KEYWORDS
,
1401 (PyCFunction
)Pakfire_open
,
1407 (PyCFunction
)Pakfire_refresh
,
1413 (PyCFunction
)Pakfire_repo_compose
,
1414 METH_VARARGS
|METH_KEYWORDS
,
1419 (PyCFunction
)Pakfire_search
,
1420 METH_VARARGS
|METH_KEYWORDS
,
1425 (PyCFunction
)Pakfire_shell
,
1426 METH_VARARGS
|METH_KEYWORDS
,
1431 (PyCFunction
)Pakfire_sync
,
1432 METH_VARARGS
|METH_KEYWORDS
,
1437 (PyCFunction
)Pakfire_update
,
1438 METH_VARARGS
|METH_KEYWORDS
,
1443 (PyCFunction
)Pakfire_version_compare
,
1449 (PyCFunction
)Pakfire_whatprovides
,
1455 (PyCFunction
)Pakfire_whatrequires
,
1462 static struct PyGetSetDef Pakfire_getsetters
[] = {
1465 (getter
)Pakfire_get_arch
,
1472 (getter
)Pakfire_get_keys
,
1479 (getter
)Pakfire_get_path
,
1486 (getter
)Pakfire_get_repos
,
1494 PyTypeObject PakfireType
= {
1495 PyVarObject_HEAD_INIT(NULL
, 0)
1496 tp_name
: "_pakfire.Pakfire",
1497 tp_basicsize
: sizeof(PakfireObject
),
1498 tp_flags
: Py_TPFLAGS_DEFAULT
|Py_TPFLAGS_BASETYPE
,
1499 tp_new
: Pakfire_new
,
1500 tp_dealloc
: (destructor
)Pakfire_dealloc
,
1501 tp_init
: (initproc
)Pakfire_init
,
1502 tp_doc
: "Pakfire object",
1503 tp_methods
: Pakfire_methods
,
1504 tp_getset
: Pakfire_getsetters
,
1505 tp_repr
: (reprfunc
)Pakfire_repr
,