summaryrefslogtreecommitdiff
path: root/python/rpmts-py.c
diff options
context:
space:
mode:
authorKim Kibum <kb0929.kim@samsung.com>2012-05-21 17:49:08 +0900
committerKim Kibum <kb0929.kim@samsung.com>2012-05-21 17:49:08 +0900
commitdec48cfa66e17ba4a7e50c92cb24b913289feb12 (patch)
treee1f48cd5cabb40a1d604b36949ff072d01267cb5 /python/rpmts-py.c
parentb7a3bffb8e0341b7e4ef69def268bca3a7f279ff (diff)
downloadrpm-dec48cfa66e17ba4a7e50c92cb24b913289feb12.tar.gz
rpm-dec48cfa66e17ba4a7e50c92cb24b913289feb12.tar.bz2
rpm-dec48cfa66e17ba4a7e50c92cb24b913289feb12.zip
Upload Tizen:Base source
Diffstat (limited to 'python/rpmts-py.c')
-rw-r--r--python/rpmts-py.c904
1 files changed, 904 insertions, 0 deletions
diff --git a/python/rpmts-py.c b/python/rpmts-py.c
new file mode 100644
index 0000000..1e8a09a
--- /dev/null
+++ b/python/rpmts-py.c
@@ -0,0 +1,904 @@
+#include "rpmsystem-py.h"
+
+#include <rpm/rpmlib.h> /* rpmReadPackageFile, headerCheck */
+#include <rpm/rpmtag.h>
+#include <rpm/rpmpgp.h>
+#include <rpm/rpmdb.h>
+#include <rpm/rpmbuild.h>
+
+#include "header-py.h"
+#include "rpmds-py.h" /* XXX for rpmdsNew */
+#include "rpmfd-py.h"
+#include "rpmkeyring-py.h"
+#include "rpmfi-py.h" /* XXX for rpmfiNew */
+#include "rpmmi-py.h"
+#include "rpmii-py.h"
+#include "rpmps-py.h"
+#include "rpmte-py.h"
+
+#include "rpmts-py.h"
+
+#include "debug.h"
+
+/** \ingroup python
+ * \name Class: Rpmts
+ * \class Rpmts
+ * \brief A python rpm.ts object represents an RPM transaction set.
+ *
+ * The transaction set is the workhorse of RPM. It performs the
+ * installation and upgrade of packages. The rpm.ts object is
+ * instantiated by the TransactionSet function in the rpm module.
+ *
+ * The TransactionSet function takes two optional arguments. The first
+ * argument is the root path. The second is the verify signature disable flags,
+ * a set of the following bits:
+ *
+ * - rpm.RPMVSF_NOHDRCHK if set, don't check rpmdb headers
+ * - rpm.RPMVSF_NEEDPAYLOAD if not set, check header+payload (if possible)
+ * - rpm.RPMVSF_NOSHA1HEADER if set, don't check header SHA1 digest
+ * - rpm.RPMVSF_NODSAHEADER if set, don't check header DSA signature
+ * - rpm.RPMVSF_NOMD5 if set, don't check header+payload MD5 digest
+ * - rpm.RPMVSF_NODSA if set, don't check header+payload DSA signature
+ * - rpm.RPMVSF_NORSA if set, don't check header+payload RSA signature
+ *
+ * For convenience, there are the following masks:
+ * - rpm._RPMVSF_NODIGESTS if set, don't check digest(s).
+ * - rpm._RPMVSF_NOSIGNATURES if set, don't check signature(s).
+ *
+ * A rpm.ts object has the following methods:
+ *
+ * - addInstall(hdr,data,mode) Add an install element to a transaction set.
+ * @param hdr the header to be added
+ * @param data user data that will be passed to the transaction callback
+ * during transaction execution
+ * @param mode optional argument that specifies if this package should
+ * be installed ('i'), upgraded ('u').
+ *
+ * - addErase(name) Add an erase element to a transaction set.
+ * @param name the package name to be erased
+ *
+ * - check() Perform a dependency check on the transaction set. After
+ * headers have been added to a transaction set, a dependency
+ * check can be performed to make sure that all package
+ * dependencies are satisfied.
+ * @return None If there are no unresolved dependencies
+ * Otherwise a list of complex tuples is returned, one tuple per
+ * unresolved dependency, with
+ * The format of the dependency tuple is:
+ * ((packageName, packageVersion, packageRelease),
+ * (reqName, reqVersion),
+ * needsFlags,
+ * suggestedPackage,
+ * sense)
+ * packageName, packageVersion, packageRelease are the name,
+ * version, and release of the package that has the unresolved
+ * dependency or conflict.
+ * The reqName and reqVersion are the name and version of the
+ * requirement or conflict.
+ * The needsFlags is a bitfield that describes the versioned
+ * nature of a requirement or conflict. The constants
+ * rpm.RPMSENSE_LESS, rpm.RPMSENSE_GREATER, and
+ * rpm.RPMSENSE_EQUAL can be logical ANDed with the needsFlags
+ * to get versioned dependency information.
+ * suggestedPackage is a tuple if the dependency check was aware
+ * of a package that solves this dependency problem when the
+ * dependency check was run. Packages that are added to the
+ * transaction set as "available" are examined during the
+ * dependency check as possible dependency solvers. The tuple
+ * contains two values, (header, suggestedName). These are set to
+ * the header of the suggested package and its name, respectively.
+ * If there is no known package to solve the dependency problem,
+ * suggestedPackage is None.
+ * The constants rpm.RPMDEP_SENSE_CONFLICTS and
+ * rpm.RPMDEP_SENSE_REQUIRES are set to show a dependency as a
+ * requirement or a conflict.
+ *
+ * - ts.order() Do a topological sort of added element relations.
+ * @return None
+ *
+ * - ts.setFlags(transFlags) Set transaction set flags.
+ * @param transFlags - bit(s) to controll transaction operations. The
+ * following values can be logically OR'ed together:
+ * - rpm.RPMTRANS_FLAG_TEST - test mode, do not modify the RPM
+ * database, change any files, or run any package scripts
+ * - rpm.RPMTRANS_FLAG_BUILD_PROBS - only build a list of
+ * problems encountered when attempting to run this transaction
+ * set
+ * - rpm.RPMTRANS_FLAG_NOSCRIPTS - do not execute package scripts
+ * - rpm.RPMTRANS_FLAG_JUSTDB - only make changes to the rpm
+ * database, do not modify files.
+ * - rpm.RPMTRANS_FLAG_NOTRIGGERS - do not run trigger scripts
+ * - rpm.RPMTRANS_FLAG_NODOCS - do not install files marked as %doc
+ * - rpm.RPMTRANS_FLAG_ALLFILES - create all files, even if a
+ * file is marked %config(missingok) and an upgrade is
+ * being performed.
+ * - rpm.RPMTRANS_FLAG_KEEPOBSOLETE - do not remove obsoleted
+ * packages.
+ * @return previous transFlags
+ *
+ * - ts.setProbFilter(ignoreSet) Set transaction set problem filter.
+ * @param problemSetFilter - control bit(s) to ignore classes of problems,
+ * a logical or of one or more of the following bit(s):
+ * - rpm.RPMPROB_FILTER_IGNOREOS -
+ * - rpm.RPMPROB_FILTER_IGNOREARCH -
+ * - rpm.RPMPROB_FILTER_REPLACEPKG -
+ * - rpm.RPMPROB_FILTER_FORCERELOCATE -
+ * - rpm.RPMPROB_FILTER_REPLACENEWFILES -
+ * - rpm.RPMPROB_FILTER_REPLACEOLDFILES -
+ * - rpm.RPMPROB_FILTER_OLDPACKAGE -
+ * - rpm.RPMPROB_FILTER_DISKSPACE -
+ * @return previous ignoreSet
+ *
+ * - ts.run(callback,data) Attempt to execute a transaction set.
+ * After the transaction set has been populated with install/upgrade or
+ * erase actions, the transaction set can be executed by invoking
+ * the ts.run() method.
+ */
+
+struct rpmtsObject_s {
+ PyObject_HEAD
+ PyObject *md_dict; /*!< to look like PyModuleObject */
+ rpmfdObject *scriptFd;
+ PyObject *keyList;
+ rpmts ts;
+ rpmtsi tsi;
+};
+
+struct rpmtsCallbackType_s {
+ PyObject * cb;
+ PyObject * data;
+ rpmtsObject * tso;
+ PyThreadState *_save;
+};
+
+RPM_GNUC_NORETURN
+static void die(PyObject *cb)
+{
+ char *pyfn = NULL;
+ PyObject *r;
+
+ if (PyErr_Occurred()) {
+ PyErr_Print();
+ }
+ if ((r = PyObject_Repr(cb)) != NULL) {
+ pyfn = PyBytes_AsString(r);
+ }
+ fprintf(stderr, _("error: python callback %s failed, aborting!\n"),
+ pyfn ? pyfn : "???");
+ rpmdbCheckTerminate(1);
+ exit(EXIT_FAILURE);
+}
+
+static PyObject *
+rpmts_AddInstall(rpmtsObject * s, PyObject * args)
+{
+ Header h = NULL;
+ PyObject * key;
+ int how = 0;
+ int rc;
+
+ if (!PyArg_ParseTuple(args, "O&Oi:AddInstall",
+ hdrFromPyObject, &h, &key, &how))
+ return NULL;
+
+ rc = rpmtsAddInstallElement(s->ts, h, key, how, NULL);
+ if (key && rc == 0) {
+ PyList_Append(s->keyList, key);
+ }
+ return PyBool_FromLong((rc == 0));
+}
+
+static PyObject *
+rpmts_AddErase(rpmtsObject * s, PyObject * args)
+{
+ Header h;
+
+ if (!PyArg_ParseTuple(args, "O&:AddErase", hdrFromPyObject, &h))
+ return NULL;
+
+ return PyBool_FromLong(rpmtsAddEraseElement(s->ts, h, -1) == 0);
+}
+
+static int
+rpmts_SolveCallback(rpmts ts, rpmds ds, const void * data)
+{
+ struct rpmtsCallbackType_s * cbInfo = (struct rpmtsCallbackType_s *) data;
+ PyObject * args, * result;
+ int res = 1;
+
+ if (cbInfo->tso == NULL) return res;
+ if (cbInfo->cb == Py_None) return res;
+
+ PyEval_RestoreThread(cbInfo->_save);
+
+ args = Py_BuildValue("(Oissi)", cbInfo->tso,
+ rpmdsTagN(ds), rpmdsN(ds), rpmdsEVR(ds), rpmdsFlags(ds));
+ result = PyEval_CallObject(cbInfo->cb, args);
+ Py_DECREF(args);
+
+ if (!result) {
+ die(cbInfo->cb);
+ } else {
+ if (PyInt_Check(result))
+ res = PyInt_AsLong(result);
+ Py_DECREF(result);
+ }
+
+ cbInfo->_save = PyEval_SaveThread();
+
+ return res;
+}
+
+static PyObject *
+rpmts_Check(rpmtsObject * s, PyObject * args, PyObject * kwds)
+{
+ struct rpmtsCallbackType_s cbInfo;
+ int rc;
+ char * kwlist[] = {"callback", NULL};
+
+ memset(&cbInfo, 0, sizeof(cbInfo));
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:Check", kwlist,
+ &cbInfo.cb))
+ return NULL;
+
+ if (cbInfo.cb != NULL) {
+ if (!PyCallable_Check(cbInfo.cb)) {
+ PyErr_SetString(PyExc_TypeError, "expected a callable");
+ return NULL;
+ }
+ rc = rpmtsSetSolveCallback(s->ts, rpmts_SolveCallback, (void *)&cbInfo);
+ }
+
+ cbInfo.tso = s;
+ cbInfo._save = PyEval_SaveThread();
+
+ rc = rpmtsCheck(s->ts);
+
+ PyEval_RestoreThread(cbInfo._save);
+
+ return PyBool_FromLong((rc == 0));
+}
+
+static PyObject *
+rpmts_Order(rpmtsObject * s)
+{
+ int rc;
+
+ Py_BEGIN_ALLOW_THREADS
+ rc = rpmtsOrder(s->ts);
+ Py_END_ALLOW_THREADS
+
+ return Py_BuildValue("i", rc);
+}
+
+static PyObject *
+rpmts_Clean(rpmtsObject * s)
+{
+ rpmtsClean(s->ts);
+
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+rpmts_OpenDB(rpmtsObject * s)
+{
+ int dbmode;
+
+ dbmode = rpmtsGetDBMode(s->ts);
+ if (dbmode == -1)
+ dbmode = O_RDONLY;
+
+ return Py_BuildValue("i", rpmtsOpenDB(s->ts, dbmode));
+}
+
+static PyObject *
+rpmts_CloseDB(rpmtsObject * s)
+{
+ int rc;
+
+ rc = rpmtsCloseDB(s->ts);
+ rpmtsSetDBMode(s->ts, -1); /* XXX disable lazy opens */
+
+ return Py_BuildValue("i", rc);
+}
+
+static PyObject *
+rpmts_InitDB(rpmtsObject * s)
+{
+ int rc;
+
+ rc = rpmtsInitDB(s->ts, O_RDONLY);
+ if (rc == 0)
+ rc = rpmtsCloseDB(s->ts);
+
+ return Py_BuildValue("i", rc);
+}
+
+static PyObject *
+rpmts_RebuildDB(rpmtsObject * s)
+{
+ int rc;
+
+ Py_BEGIN_ALLOW_THREADS
+ rc = rpmtsRebuildDB(s->ts);
+ Py_END_ALLOW_THREADS
+
+ return Py_BuildValue("i", rc);
+}
+
+static PyObject *
+rpmts_VerifyDB(rpmtsObject * s)
+{
+ int rc;
+
+ Py_BEGIN_ALLOW_THREADS
+ rc = rpmtsVerifyDB(s->ts);
+ Py_END_ALLOW_THREADS
+
+ return Py_BuildValue("i", rc);
+}
+
+static PyObject *
+rpmts_HdrFromFdno(rpmtsObject * s, PyObject *arg)
+{
+ PyObject *ho = NULL;
+ rpmfdObject *fdo = NULL;
+ Header h;
+ rpmRC rpmrc;
+
+ if (!PyArg_Parse(arg, "O&:HdrFromFdno", rpmfdFromPyObject, &fdo))
+ return NULL;
+
+ Py_BEGIN_ALLOW_THREADS;
+ rpmrc = rpmReadPackageFile(s->ts, rpmfdGetFd(fdo), "rpmts_HdrFromFdno", &h);
+ Py_END_ALLOW_THREADS;
+ Py_XDECREF(fdo);
+
+ if (rpmrc == RPMRC_OK) {
+ ho = hdr_Wrap(&hdr_Type, h);
+ h = headerFree(h); /* ref held by python object */
+ } else {
+ Py_INCREF(Py_None);
+ ho = Py_None;
+ }
+ return Py_BuildValue("(iN)", rpmrc, ho);
+}
+
+static PyObject *
+rpmts_HdrCheck(rpmtsObject * s, PyObject *obj)
+{
+ PyObject * blob;
+ char * msg = NULL;
+ const void * uh;
+ int uc;
+ rpmRC rpmrc;
+
+ if (!PyArg_Parse(obj, "S:HdrCheck", &blob))
+ return NULL;
+
+ uh = PyBytes_AsString(blob);
+ uc = PyBytes_Size(blob);
+
+ Py_BEGIN_ALLOW_THREADS;
+ rpmrc = headerCheck(s->ts, uh, uc, &msg);
+ Py_END_ALLOW_THREADS;
+
+ return Py_BuildValue("(is)", rpmrc, msg);
+}
+
+static PyObject *
+rpmts_PgpPrtPkts(rpmtsObject * s, PyObject * args, PyObject * kwds)
+{
+ PyObject * blob;
+ unsigned char * pkt;
+ unsigned int pktlen;
+ int rc;
+ char * kwlist[] = {"octets", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "S:PgpPrtPkts", kwlist, &blob))
+ return NULL;
+
+ pkt = (unsigned char *)PyBytes_AsString(blob);
+ pktlen = PyBytes_Size(blob);
+
+ rc = pgpPrtPkts(pkt, pktlen, NULL, 1);
+
+ return Py_BuildValue("i", rc);
+}
+
+static PyObject *
+rpmts_PgpImportPubkey(rpmtsObject * s, PyObject * args, PyObject * kwds)
+{
+ PyObject * blob;
+ unsigned char * pkt;
+ unsigned int pktlen;
+ int rc;
+ char * kwlist[] = {"pubkey", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "S:PgpImportPubkey",
+ kwlist, &blob))
+ return NULL;
+
+ pkt = (unsigned char *)PyBytes_AsString(blob);
+ pktlen = PyBytes_Size(blob);
+
+ rc = rpmtsImportPubkey(s->ts, pkt, pktlen);
+
+ return Py_BuildValue("i", rc);
+}
+
+static PyObject *rpmts_setKeyring(rpmtsObject *s, PyObject *arg)
+{
+ rpmKeyring keyring = NULL;
+ if (arg == Py_None || rpmKeyringFromPyObject(arg, &keyring)) {
+ return PyBool_FromLong(rpmtsSetKeyring(s->ts, keyring) == 0);
+ } else {
+ PyErr_SetString(PyExc_TypeError, "rpm.keyring or None expected");
+ return NULL;
+ }
+}
+
+static PyObject *rpmts_getKeyring(rpmtsObject *s, PyObject *args, PyObject *kwds)
+{
+ rpmKeyring keyring = NULL;
+ int autoload = 1;
+ char * kwlist[] = { "autoload", NULL };
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i:getKeyring",
+ kwlist, &autoload))
+ return NULL;
+
+ keyring = rpmtsGetKeyring(s->ts, autoload);
+ if (keyring) {
+ return rpmKeyring_Wrap(&rpmKeyring_Type, keyring);
+ } else {
+ Py_RETURN_NONE;
+ }
+}
+
+static void *
+rpmtsCallback(const void * hd, const rpmCallbackType what,
+ const rpm_loff_t amount, const rpm_loff_t total,
+ const void * pkgKey, rpmCallbackData data)
+{
+ Header h = (Header) hd;
+ struct rpmtsCallbackType_s * cbInfo = data;
+ PyObject * pkgObj = (PyObject *) pkgKey;
+ PyObject * args, * result;
+ static FD_t fd;
+
+ if (cbInfo->cb == Py_None) return NULL;
+
+ /* Synthesize a python object for callback (if necessary). */
+ if (pkgObj == NULL) {
+ if (h) {
+ pkgObj = Py_BuildValue("s", headerGetString(h, RPMTAG_NAME));
+ } else {
+ pkgObj = Py_None;
+ Py_INCREF(pkgObj);
+ }
+ } else
+ Py_INCREF(pkgObj);
+
+ PyEval_RestoreThread(cbInfo->_save);
+
+ args = Py_BuildValue("(iLLOO)", what, amount, total, pkgObj, cbInfo->data);
+ result = PyEval_CallObject(cbInfo->cb, args);
+ Py_DECREF(args);
+ Py_DECREF(pkgObj);
+
+ if (!result) {
+ die(cbInfo->cb);
+ }
+
+ if (what == RPMCALLBACK_INST_OPEN_FILE) {
+ int fdno;
+
+ if (!PyArg_Parse(result, "i", &fdno)) {
+ die(cbInfo->cb);
+ }
+ Py_DECREF(result);
+ cbInfo->_save = PyEval_SaveThread();
+
+ fd = fdDup(fdno);
+ fcntl(Fileno(fd), F_SETFD, FD_CLOEXEC);
+
+ return fd;
+ } else
+ if (what == RPMCALLBACK_INST_CLOSE_FILE) {
+ Fclose (fd);
+ }
+
+ Py_DECREF(result);
+ cbInfo->_save = PyEval_SaveThread();
+
+ return NULL;
+}
+
+static PyObject *
+rpmts_Problems(rpmtsObject * s)
+{
+ rpmps ps = rpmtsProblems(s->ts);
+ PyObject *problems = rpmps_AsList(ps);
+ rpmpsFree(ps);
+ return problems;
+}
+
+static PyObject *
+rpmts_Run(rpmtsObject * s, PyObject * args, PyObject * kwds)
+{
+ int rc;
+ struct rpmtsCallbackType_s cbInfo;
+ rpmprobFilterFlags ignoreSet;
+ char * kwlist[] = {"callback", "data", "ignoreSet", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOi:Run", kwlist,
+ &cbInfo.cb, &cbInfo.data, &ignoreSet))
+ return NULL;
+
+ cbInfo.tso = s;
+ cbInfo._save = PyEval_SaveThread();
+
+ if (cbInfo.cb != NULL) {
+ if (!PyCallable_Check(cbInfo.cb)) {
+ PyErr_SetString(PyExc_TypeError, "expected a callable");
+ return NULL;
+ }
+ (void) rpmtsSetNotifyCallback(s->ts, rpmtsCallback, (void *) &cbInfo);
+ }
+
+ rc = rpmtsRun(s->ts, NULL, ignoreSet);
+
+ if (cbInfo.cb)
+ (void) rpmtsSetNotifyCallback(s->ts, NULL, NULL);
+
+ PyEval_RestoreThread(cbInfo._save);
+
+ return Py_BuildValue("i", rc);
+}
+
+static PyObject *
+rpmts_iternext(rpmtsObject * s)
+{
+ PyObject * result = NULL;
+ rpmte te;
+
+ /* Reset iterator on 1st entry. */
+ if (s->tsi == NULL) {
+ s->tsi = rpmtsiInit(s->ts);
+ if (s->tsi == NULL)
+ return NULL;
+ }
+
+ te = rpmtsiNext(s->tsi, 0);
+ if (te != NULL) {
+ result = rpmte_Wrap(&rpmte_Type, te);
+ } else {
+ s->tsi = rpmtsiFree(s->tsi);
+ }
+
+ return result;
+}
+
+static PyObject *
+rpmts_Match(rpmtsObject * s, PyObject * args, PyObject * kwds)
+{
+ PyObject *Key = NULL;
+ PyObject *str = NULL;
+ PyObject *mio = NULL;
+ char *key = NULL;
+/* XXX lkey *must* be a 32 bit integer, int "works" on all known platforms. */
+ int lkey = 0;
+ int len = 0;
+ rpmDbiTagVal tag = RPMDBI_PACKAGES;
+ char * kwlist[] = {"tagNumber", "key", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O&O:Match", kwlist,
+ tagNumFromPyObject, &tag, &Key))
+ return NULL;
+
+ if (Key) {
+ if (PyInt_Check(Key)) {
+ lkey = PyInt_AsLong(Key);
+ key = (char *)&lkey;
+ len = sizeof(lkey);
+ } else if (utf8FromPyObject(Key, &str)) {
+ key = PyBytes_AsString(str);
+ len = PyBytes_Size(str);
+ } else {
+ PyErr_SetString(PyExc_TypeError, "unknown key type");
+ return NULL;
+ }
+ /* One of the conversions above failed, exception is set already */
+ if (PyErr_Occurred()) goto exit;
+ }
+
+ /* XXX If not already opened, open the database O_RDONLY now. */
+ /* XXX FIXME: lazy default rdonly open also done by rpmtsInitIterator(). */
+ if (rpmtsGetRdb(s->ts) == NULL) {
+ int rc = rpmtsOpenDB(s->ts, O_RDONLY);
+ if (rc || rpmtsGetRdb(s->ts) == NULL) {
+ PyErr_SetString(pyrpmError, "rpmdb open failed");
+ goto exit;
+ }
+ }
+
+ mio = rpmmi_Wrap(&rpmmi_Type, rpmtsInitIterator(s->ts, tag, key, len), (PyObject*)s);
+
+exit:
+ Py_XDECREF(str);
+ return mio;
+}
+static PyObject *
+rpmts_index(rpmtsObject * s, PyObject * args, PyObject * kwds)
+{
+ rpmDbiTagVal tag;
+ PyObject *mio = NULL;
+ char * kwlist[] = {"tag", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&:Keys", kwlist,
+ tagNumFromPyObject, &tag))
+ return NULL;
+
+ /* XXX If not already opened, open the database O_RDONLY now. */
+ if (rpmtsGetRdb(s->ts) == NULL) {
+ int rc = rpmtsOpenDB(s->ts, O_RDONLY);
+ if (rc || rpmtsGetRdb(s->ts) == NULL) {
+ PyErr_SetString(pyrpmError, "rpmdb open failed");
+ goto exit;
+ }
+ }
+
+ rpmdbIndexIterator ii = rpmdbIndexIteratorInit(rpmtsGetRdb(s->ts), tag);
+ if (ii == NULL) {
+ PyErr_SetString(PyExc_KeyError, "No index for this tag");
+ return NULL;
+ }
+ mio = rpmii_Wrap(&rpmii_Type, ii, (PyObject*)s);
+
+exit:
+ return mio;
+}
+
+static struct PyMethodDef rpmts_methods[] = {
+ {"addInstall", (PyCFunction) rpmts_AddInstall, METH_VARARGS,
+ NULL },
+ {"addErase", (PyCFunction) rpmts_AddErase, METH_VARARGS|METH_KEYWORDS,
+ NULL },
+ {"check", (PyCFunction) rpmts_Check, METH_VARARGS|METH_KEYWORDS,
+ NULL },
+ {"order", (PyCFunction) rpmts_Order, METH_NOARGS,
+ NULL },
+ {"problems", (PyCFunction) rpmts_Problems, METH_NOARGS,
+"ts.problems() -> ps\n\
+- Return current problem set.\n" },
+ {"run", (PyCFunction) rpmts_Run, METH_VARARGS|METH_KEYWORDS,
+"ts.run(callback, data) -> (problems)\n\
+- Run a transaction set, returning list of problems found.\n\
+ Note: The callback may not be None.\n" },
+ {"clean", (PyCFunction) rpmts_Clean, METH_NOARGS,
+ NULL },
+ {"openDB", (PyCFunction) rpmts_OpenDB, METH_NOARGS,
+"ts.openDB() -> None\n\
+- Open the default transaction rpmdb.\n\
+ Note: The transaction rpmdb is lazily opened, so ts.openDB() is seldom needed.\n" },
+ {"closeDB", (PyCFunction) rpmts_CloseDB, METH_NOARGS,
+"ts.closeDB() -> None\n\
+- Close the default transaction rpmdb.\n\
+ Note: ts.closeDB() disables lazy opens, and should hardly ever be used.\n" },
+ {"initDB", (PyCFunction) rpmts_InitDB, METH_NOARGS,
+"ts.initDB() -> None\n\
+- Initialize the default transaction rpmdb.\n\
+ Note: ts.initDB() is seldom needed anymore.\n" },
+ {"rebuildDB", (PyCFunction) rpmts_RebuildDB, METH_NOARGS,
+"ts.rebuildDB() -> None\n\
+- Rebuild the default transaction rpmdb.\n" },
+ {"verifyDB", (PyCFunction) rpmts_VerifyDB, METH_NOARGS,
+"ts.verifyDB() -> None\n\
+- Verify the default transaction rpmdb.\n" },
+ {"hdrFromFdno",(PyCFunction) rpmts_HdrFromFdno,METH_O,
+"ts.hdrFromFdno(fdno) -> hdr\n\
+- Read a package header from a file descriptor.\n" },
+ {"hdrCheck", (PyCFunction) rpmts_HdrCheck, METH_O,
+ NULL },
+ {"pgpPrtPkts", (PyCFunction) rpmts_PgpPrtPkts, METH_VARARGS|METH_KEYWORDS,
+ NULL },
+ {"pgpImportPubkey", (PyCFunction) rpmts_PgpImportPubkey, METH_VARARGS|METH_KEYWORDS,
+ NULL },
+ {"getKeyring", (PyCFunction) rpmts_getKeyring, METH_VARARGS|METH_KEYWORDS,
+ NULL },
+ {"setKeyring", (PyCFunction) rpmts_setKeyring, METH_O,
+ NULL },
+ {"dbMatch", (PyCFunction) rpmts_Match, METH_VARARGS|METH_KEYWORDS,
+"ts.dbMatch([TagN, [key]]) -> mi\n\
+- Create a match iterator for the default transaction rpmdb.\n" },
+ {"dbIndex", (PyCFunction) rpmts_index, METH_VARARGS|METH_KEYWORDS,
+"ts.dbIndex(TagN) -> ii\n\
+- Create a key iterator for the default transaction rpmdb.\n" },
+ {NULL, NULL} /* sentinel */
+};
+
+static void rpmts_dealloc(rpmtsObject * s)
+{
+
+ s->ts = rpmtsFree(s->ts);
+ Py_XDECREF(s->scriptFd);
+ Py_XDECREF(s->keyList);
+ Py_TYPE(s)->tp_free((PyObject *)s);
+}
+
+static PyObject * rpmts_new(PyTypeObject * subtype, PyObject *args, PyObject *kwds)
+{
+ rpmtsObject * s = (rpmtsObject *)subtype->tp_alloc(subtype, 0);
+ if (s == NULL) return NULL;
+
+ s->ts = rpmtsCreate();
+ s->scriptFd = NULL;
+ s->tsi = NULL;
+ s->keyList = PyList_New(0);
+ return (PyObject *) s;
+}
+
+static int rpmts_init(rpmtsObject *s, PyObject *args, PyObject *kwds)
+{
+ char * rootDir = "/";
+ rpmVSFlags vsflags = rpmExpandNumeric("%{?__vsflags}");
+ char * kwlist[] = {"rootdir", "vsflags", 0};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|si:rpmts_new", kwlist,
+ &rootDir, &vsflags))
+ return -1;
+
+ (void) rpmtsSetRootDir(s->ts, rootDir);
+ /* XXX: make this use common code with rpmts_SetVSFlags() to check the
+ * python objects */
+ (void) rpmtsSetVSFlags(s->ts, vsflags);
+
+ return 0;
+}
+
+static PyObject *rpmts_get_tid(rpmtsObject *s, void *closure)
+{
+ return Py_BuildValue("i", rpmtsGetTid(s->ts));
+}
+
+static PyObject *rpmts_get_rootDir(rpmtsObject *s, void *closure)
+{
+ return Py_BuildValue("s", rpmtsRootDir(s->ts));
+}
+
+static int rpmts_set_scriptFd(rpmtsObject *s, PyObject *value, void *closure)
+{
+ rpmfdObject *fdo = NULL;
+ int rc = 0;
+ if (PyArg_Parse(value, "O&", rpmfdFromPyObject, &fdo)) {
+ Py_XDECREF(s->scriptFd);
+ s->scriptFd = fdo;
+ rpmtsSetScriptFd(s->ts, rpmfdGetFd(s->scriptFd));
+ } else if (value == Py_None) {
+ Py_XDECREF(s->scriptFd);
+ s->scriptFd = NULL;
+ rpmtsSetScriptFd(s->ts, NULL);
+ } else {
+ rc = -1;
+ }
+ return rc;
+}
+
+static PyObject *rpmts_get_color(rpmtsObject *s, void *closure)
+{
+ return Py_BuildValue("i", rpmtsColor(s->ts));
+}
+
+static PyObject *rpmts_get_prefcolor(rpmtsObject *s, void *closure)
+{
+ return Py_BuildValue("i", rpmtsPrefColor(s->ts));
+}
+
+static int rpmts_set_color(rpmtsObject *s, PyObject *value, void *closure)
+{
+ rpm_color_t color;
+ if (!PyArg_Parse(value, "i", &color)) return -1;
+
+ /* TODO: validate the bits */
+ rpmtsSetColor(s->ts, color);
+ return 0;
+}
+
+static int rpmts_set_prefcolor(rpmtsObject *s, PyObject *value, void *closure)
+{
+ rpm_color_t color;
+ if (!PyArg_Parse(value, "i", &color)) return -1;
+
+ /* TODO: validate the bits */
+ rpmtsSetPrefColor(s->ts, color);
+ return 0;
+}
+
+static int rpmts_set_flags(rpmtsObject *s, PyObject *value, void *closure)
+{
+ rpmtransFlags flags;
+ if (!PyArg_Parse(value, "i", &flags)) return -1;
+
+ /* TODO: validate the bits */
+ rpmtsSetFlags(s->ts, flags);
+ return 0;
+}
+
+static int rpmts_set_vsflags(rpmtsObject *s, PyObject *value, void *closure)
+{
+ rpmVSFlags flags;
+ if (!PyArg_Parse(value, "i", &flags)) return -1;
+
+ /* TODO: validate the bits */
+ rpmtsSetVSFlags(s->ts, flags);
+ return 0;
+}
+
+static PyObject *rpmts_get_flags(rpmtsObject *s, void *closure)
+{
+ return Py_BuildValue("i", rpmtsFlags(s->ts));
+}
+
+static PyObject *rpmts_get_vsflags(rpmtsObject *s, void *closure)
+{
+ return Py_BuildValue("i", rpmtsVSFlags(s->ts));
+}
+
+static char rpmts_doc[] =
+"";
+
+static PyGetSetDef rpmts_getseters[] = {
+ /* only provide a setter until we have rpmfd wrappings */
+ {"scriptFd", NULL, (setter)rpmts_set_scriptFd, NULL },
+ {"tid", (getter)rpmts_get_tid, NULL, NULL },
+ {"rootDir", (getter)rpmts_get_rootDir, NULL, NULL },
+ {"_color", (getter)rpmts_get_color, (setter)rpmts_set_color, NULL},
+ {"_prefcolor", (getter)rpmts_get_prefcolor, (setter)rpmts_set_prefcolor, NULL},
+ {"_flags", (getter)rpmts_get_flags, (setter)rpmts_set_flags, NULL},
+ {"_vsflags", (getter)rpmts_get_vsflags, (setter)rpmts_set_vsflags, NULL},
+ { NULL }
+};
+
+PyTypeObject rpmts_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "rpm.ts", /* tp_name */
+ sizeof(rpmtsObject), /* tp_size */
+ 0, /* tp_itemsize */
+ (destructor) rpmts_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ (getattrfunc)0, /* tp_getattr */
+ (setattrfunc)0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ PyObject_GenericGetAttr, /* tp_getattro */
+ PyObject_GenericSetAttr, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */
+ rpmts_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ PyObject_SelfIter, /* tp_iter */
+ (iternextfunc) rpmts_iternext, /* tp_iternext */
+ rpmts_methods, /* tp_methods */
+ 0, /* tp_members */
+ rpmts_getseters, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc) rpmts_init, /* tp_init */
+ 0, /* tp_alloc */
+ (newfunc) rpmts_new, /* tp_new */
+ 0, /* tp_free */
+ 0, /* tp_is_gc */
+};