cr_Repomd *repomd_obj = cr_repomd_new();
- cr_RepomdRecord *pri_xml_rec = cr_repomd_record_new(pri_xml_filename);
- cr_RepomdRecord *fil_xml_rec = cr_repomd_record_new(fil_xml_filename);
- cr_RepomdRecord *oth_xml_rec = cr_repomd_record_new(oth_xml_filename);
+ cr_RepomdRecord *pri_xml_rec = cr_repomd_record_new(pri_xml_filename, "primary");
+ cr_RepomdRecord *fil_xml_rec = cr_repomd_record_new(fil_xml_filename, "filelists");
+ cr_RepomdRecord *oth_xml_rec = cr_repomd_record_new(oth_xml_filename, "other");
cr_RepomdRecord *pri_db_rec = NULL;
cr_RepomdRecord *fil_db_rec = NULL;
cr_RepomdRecord *oth_db_rec = NULL;
// Groupfile
if (groupfile) {
- groupfile_rec = cr_repomd_record_new(groupfile);
- compressed_groupfile_rec = cr_repomd_record_new(groupfile);
+ groupfile_rec = cr_repomd_record_new(groupfile, "group");
+ compressed_groupfile_rec = cr_repomd_record_new(groupfile, "group_gz");
cr_repomd_record_compress_and_fill(groupfile_rec,
compressed_groupfile_rec,
cmd_options->checksum_type,
// Updateinfo
if (updateinfo) {
- updateinfo_rec = cr_repomd_record_new(updateinfo);
+ updateinfo_rec = cr_repomd_record_new(updateinfo, "updateinfo");
cr_repomd_record_fill(updateinfo_rec, cmd_options->checksum_type, NULL);
}
// Prepare repomd records
- pri_db_rec = cr_repomd_record_new(pri_db_name);
- fil_db_rec = cr_repomd_record_new(fil_db_name);
- oth_db_rec = cr_repomd_record_new(oth_db_name);
+ pri_db_rec = cr_repomd_record_new(pri_db_name, "primary_db");
+ fil_db_rec = cr_repomd_record_new(fil_db_name, "filelists_db");
+ oth_db_rec = cr_repomd_record_new(oth_db_name, "other_db");
cr_repomd_record_fill(pri_db_rec, cmd_options->checksum_type, NULL);
cr_repomd_record_fill(fil_db_rec, cmd_options->checksum_type, NULL);
// Gen xml
- cr_repomd_set_record(repomd_obj, pri_xml_rec, "primary");
- cr_repomd_set_record(repomd_obj, fil_xml_rec, "filelists");
- cr_repomd_set_record(repomd_obj, oth_xml_rec, "other");
- cr_repomd_set_record(repomd_obj, pri_db_rec, "primary_db");
- cr_repomd_set_record(repomd_obj, fil_db_rec, "filelists_db");
- cr_repomd_set_record(repomd_obj, oth_db_rec, "other_db");
- cr_repomd_set_record(repomd_obj, groupfile_rec, "group");
- cr_repomd_set_record(repomd_obj, compressed_groupfile_rec, "group_gz");
- cr_repomd_set_record(repomd_obj, updateinfo_rec, "updateinfo");
+ cr_repomd_set_record(repomd_obj, pri_xml_rec);
+ cr_repomd_set_record(repomd_obj, fil_xml_rec);
+ cr_repomd_set_record(repomd_obj, oth_xml_rec);
+ cr_repomd_set_record(repomd_obj, pri_db_rec);
+ cr_repomd_set_record(repomd_obj, fil_db_rec);
+ cr_repomd_set_record(repomd_obj, oth_db_rec);
+ cr_repomd_set_record(repomd_obj, groupfile_rec);
+ cr_repomd_set_record(repomd_obj, compressed_groupfile_rec);
+ cr_repomd_set_record(repomd_obj, updateinfo_rec);
int i = 0;
while (cmd_options->repo_tags && cmd_options->repo_tags[i])
// Prepare repomd records
- cr_RepomdRecord *pri_xml_rec = cr_repomd_record_new(pri_xml_filename);
- cr_RepomdRecord *fil_xml_rec = cr_repomd_record_new(fil_xml_filename);
- cr_RepomdRecord *oth_xml_rec = cr_repomd_record_new(oth_xml_filename);
+ cr_RepomdRecord *pri_xml_rec = cr_repomd_record_new(pri_xml_filename, "primary");
+ cr_RepomdRecord *fil_xml_rec = cr_repomd_record_new(fil_xml_filename, "filelists");
+ cr_RepomdRecord *oth_xml_rec = cr_repomd_record_new(oth_xml_filename, "other");
cr_RepomdRecord *pri_db_rec = NULL;
cr_RepomdRecord *fil_db_rec = NULL;
cr_RepomdRecord *oth_db_rec = NULL;
// Groupfile
if (groupfile) {
- groupfile_rec = cr_repomd_record_new(groupfile);
- compressed_groupfile_rec = cr_repomd_record_new(groupfile);
+ groupfile_rec = cr_repomd_record_new(groupfile, "group");
+ compressed_groupfile_rec = cr_repomd_record_new(groupfile, "group_gz");
cr_repomd_record_compress_and_fill(groupfile_rec,
compressed_groupfile_rec,
CR_CHECKSUM_SHA256,
// Update info
if (!cmd_options->noupdateinfo) {
- update_info_rec = cr_repomd_record_new(update_info_filename);
+ update_info_rec = cr_repomd_record_new(update_info_filename, "updateinfo");
cr_repomd_record_fill(update_info_rec, CR_CHECKSUM_SHA256, NULL);
}
if (cmd_options->koji) {
gchar *pkgorigins_path = g_strconcat(cmd_options->tmp_out_repo, "pkgorigins.gz", NULL);
- pkgorigins_rec = cr_repomd_record_new(pkgorigins_path);
+ pkgorigins_rec = cr_repomd_record_new(pkgorigins_path, "origin");
cr_repomd_record_fill(pkgorigins_rec, CR_CHECKSUM_SHA256, NULL);
g_free(pkgorigins_path);
}
remove(oth_db_filename);
// Prepare repomd records
- pri_db_rec = cr_repomd_record_new(pri_db_c_filename);
- fil_db_rec = cr_repomd_record_new(fil_db_c_filename);
- oth_db_rec = cr_repomd_record_new(oth_db_c_filename);
+ pri_db_rec = cr_repomd_record_new(pri_db_c_filename, "primary_db");
+ fil_db_rec = cr_repomd_record_new(fil_db_c_filename, "filelists_db");
+ oth_db_rec = cr_repomd_record_new(oth_db_c_filename, "other_db");
g_free(pri_db_filename);
g_free(fil_db_filename);
// Gen repomd.xml content
cr_Repomd *repomd_obj = cr_repomd_new();
- cr_repomd_set_record(repomd_obj, pri_xml_rec, "primary");
- cr_repomd_set_record(repomd_obj, fil_xml_rec, "filelists");
- cr_repomd_set_record(repomd_obj, oth_xml_rec, "other");
- cr_repomd_set_record(repomd_obj, pri_db_rec, "primary_db");
- cr_repomd_set_record(repomd_obj, fil_db_rec, "filelists_db");
- cr_repomd_set_record(repomd_obj, oth_db_rec, "other_db");
- cr_repomd_set_record(repomd_obj, groupfile_rec, "group");
- cr_repomd_set_record(repomd_obj, compressed_groupfile_rec, "group_gz");
- cr_repomd_set_record(repomd_obj, update_info_rec,"updateinfo");
- cr_repomd_set_record(repomd_obj, pkgorigins_rec, "origin");
+ cr_repomd_set_record(repomd_obj, pri_xml_rec);
+ cr_repomd_set_record(repomd_obj, fil_xml_rec);
+ cr_repomd_set_record(repomd_obj, oth_xml_rec);
+ cr_repomd_set_record(repomd_obj, pri_db_rec);
+ cr_repomd_set_record(repomd_obj, fil_db_rec);
+ cr_repomd_set_record(repomd_obj, oth_db_rec);
+ cr_repomd_set_record(repomd_obj, groupfile_rec);
+ cr_repomd_set_record(repomd_obj, compressed_groupfile_rec);
+ cr_repomd_set_record(repomd_obj, update_info_rec);
+ cr_repomd_set_record(repomd_obj, pkgorigins_rec);
char *repomd_xml = cr_repomd_xml_dump(repomd_obj);
class RepomdRecord(_createrepo_c.RepomdRecord):
def compress_and_fill(self, hashtype, compresstype):
- rec = RepomdRecord("")
+ rec = RepomdRecord(self.type + "_gz", None)
_createrepo_c.RepomdRecord.compress_and_fill(self, rec, hashtype, compresstype)
return rec
xml_parse_primary = _createrepo_c.xml_parse_primary
xml_parse_filelists = _createrepo_c.xml_parse_filelists
xml_parse_other = _createrepo_c.xml_parse_other
+xml_parse_repomd = _createrepo_c.xml_parse_repomd
def package_from_rpm(filename, checksum_type=SHA256, location_href=None,
location_base=None, changelog_limit=10):
METH_VARARGS, NULL},
{"xml_parse_other", (PyCFunction)py_xml_parse_other,
METH_VARARGS, NULL},
+ {"xml_parse_repomd", (PyCFunction)py_xml_parse_repomd,
+ METH_VARARGS, NULL},
{ NULL }
};
if (check_MetadataStatus(self))
return NULL;
+
GList *keys = g_hash_table_get_keys(self->md->ht);
PyObject *list = PyList_New(0);
+
for (GList *elem = keys; elem; elem = g_list_next(elem)) {
PyObject *py_str = PyString_FromString(elem->data);
assert(py_str);
if (PyList_Append(list, py_str) == -1) {
Py_XDECREF(list);
+ g_list_free(keys);
return NULL;
}
}
+
+ g_list_free(keys);
return list;
}
cr_Repomd *repomd;
} _RepomdObject;
-static int
+cr_Repomd *
+Repomd_FromPyObject(PyObject *o)
+{
+ if (!RepomdObject_Check(o)) {
+ PyErr_SetString(PyExc_TypeError, "Expected a createrepo_c.Repomd object.");
+ return NULL;
+ }
+ return ((_RepomdObject *)o)->repomd;
+}
+
+ static int
check_RepomdStatus(const _RepomdObject *self)
{
assert(self != NULL);
set_record(_RepomdObject *self, PyObject *args)
{
PyObject *record;
- char *type;
+ cr_RepomdRecord *orig, *new;
- if (!PyArg_ParseTuple(args, "O!s:set_record", &RepomdRecord_Type, &record, &type))
+ if (!PyArg_ParseTuple(args, "O!:set_record", &RepomdRecord_Type, &record))
return NULL;
if (check_RepomdStatus(self))
return NULL;
- cr_repomd_set_record(self->repomd, RepomdRecord_FromPyObject(record), type);
- Py_XINCREF(record);
+
+ orig = RepomdRecord_FromPyObject(record);
+ new = cr_repomd_record_copy(orig);
+ cr_repomd_set_record(self->repomd, new);
Py_RETURN_NONE;
}
{NULL} /* sentinel */
};
+/* Convertors for getsetters */
+
+/** Convert C object to PyObject.
+ * @param C object
+ * @return PyObject representation
+ */
+typedef PyObject *(*ConversionFromFunc)(void *);
+
+/** Check an element from a list if has a valid format.
+ * @param a single list element
+ * @return 0 if ok, 1 otherwise
+ */
+typedef int (*ConversionToCheckFunc)(PyObject *);
+
+/** Convert PyObject to C representation.
+ * @param PyObject
+ * @return C representation
+ */
+typedef void *(*ConversionToFunc)(PyObject *, GStringChunk *);
+
+static int
+CheckPyString(PyObject *dep)
+{
+ if (!PyString_Check(dep)) {
+ PyErr_SetString(PyExc_ValueError, "Element of list has to be a string");
+ return 1;
+ }
+ return 0;
+}
+
+static int
+CheckPyDistroTag(PyObject *dep)
+{
+ if (!PyTuple_Check(dep) || PyTuple_Size(dep) != 2) {
+ PyErr_SetString(PyExc_ValueError, "Element of list has to be a tuple with 2 items.");
+ return 1;
+ }
+ return 0;
+}
+
+PyObject *
+PyObject_FromRepomdRecord(cr_RepomdRecord *rec)
+{
+ return Object_FromRepomdRecord(cr_repomd_record_copy(rec));
+}
+
+typedef struct {
+ size_t offset; /*!< Ofset of the list in cr_Repomd */
+ ConversionFromFunc f; /*!< Conversion func to PyObject from a C object */
+ ConversionToCheckFunc t_check; /*!< Check func for a single element of list */
+ ConversionToFunc t; /*!< Conversion func to C object from PyObject */
+} ListConvertor;
+
+/** List of convertors for converting a lists in cr_Package. */
+static ListConvertor list_convertors[] = {
+ { offsetof(cr_Repomd, repo_tags), PyStringOrNone_FromString,
+ CheckPyString, PyObject_ToChunkedString },
+ { offsetof(cr_Repomd, distro_tags), PyObject_FromDistroTag,
+ CheckPyDistroTag, PyObject_ToDistroTag },
+ { offsetof(cr_Repomd, content_tags), PyStringOrNone_FromString,
+ CheckPyString, PyObject_ToChunkedString },
+ { offsetof(cr_Repomd, records), PyObject_FromRepomdRecord,
+ NULL, NULL },
+};
+
+/* Getters */
+
+static PyObject *
+get_str(_RepomdObject *self, void *member_offset)
+{
+ if (check_RepomdStatus(self))
+ return NULL;
+ cr_Repomd *repomd = self->repomd;
+ char *str = *((char **) ((size_t) repomd + (size_t) member_offset));
+ if (str == NULL)
+ Py_RETURN_NONE;
+ return PyString_FromString(str);
+}
+
+static PyObject *
+get_list(_RepomdObject *self, void *conv)
+{
+ ListConvertor *convertor = conv;
+ PyObject *list;
+ cr_Repomd *repomd = self->repomd;
+ GSList *glist = *((GSList **) ((size_t) repomd + (size_t) convertor->offset));
+
+ if (check_RepomdStatus(self))
+ return NULL;
+
+ if ((list = PyList_New(0)) == NULL)
+ return NULL;
+
+ for (GSList *elem = glist; elem; elem = g_slist_next(elem))
+ PyList_Append(list, convertor->f(elem->data));
+
+ return list;
+}
+
+/* Setters */
+
+static int
+set_str(_RepomdObject *self, PyObject *value, void *member_offset)
+{
+ if (check_RepomdStatus(self))
+ return -1;
+ if (!PyString_Check(value)) {
+ PyErr_SetString(PyExc_ValueError, "String expected!");
+ return -1;
+ }
+ cr_Repomd *repomd = self->repomd;
+
+ char *str = g_string_chunk_insert(repomd->chunk, PyString_AsString(value));
+ *((char **) ((size_t) repomd + (size_t) member_offset)) = str;
+ return 0;
+}
+
+static int
+set_list(_RepomdObject *self, PyObject *list, void *conv)
+{
+ ListConvertor *convertor = conv;
+ cr_Repomd *repomd = self->repomd;
+ GSList *glist = NULL;
+
+ if (check_RepomdStatus(self))
+ return -1;
+
+ if (!PyList_Check(list)) {
+ PyErr_SetString(PyExc_ValueError, "List expected!");
+ return -1;
+ }
+
+ Py_ssize_t len = PyList_Size(list);
+
+ // Check all elements
+ for (Py_ssize_t x = 0; x < len; x++) {
+ PyObject *elem = PyList_GetItem(list, x);
+ if (convertor->t_check && convertor->t_check(elem))
+ return -1;
+ }
+
+ for (Py_ssize_t x = 0; x < len; x++) {
+ glist = g_slist_prepend(glist,
+ convertor->t(PyList_GetItem(list, x), repomd->chunk));
+ }
+
+ *((GSList **) ((size_t) repomd + (size_t) convertor->offset)) = glist;
+ return 0;
+}
+
+/** Return offset of a selected member of cr_Repomd structure. */
+#define OFFSET(member) (void *) offsetof(cr_Repomd, member)
+
+static PyGetSetDef repomd_getsetters[] = {
+ {"revision", (getter)get_str, (setter)set_str, NULL, OFFSET(revision)},
+ {"repo_tags", (getter)get_list, (setter)set_list, NULL, &(list_convertors[0])},
+ {"distro_tags", (getter)get_list, (setter)set_list, NULL, &(list_convertors[1])},
+ {"content_tags", (getter)get_list, (setter)set_list, NULL, &(list_convertors[2])},
+ {"records", (getter)get_list, (setter)NULL, NULL, &(list_convertors[3])},
+ {NULL, NULL, NULL, NULL, NULL} /* sentinel */
+};
+
+/* Object */
+
+
PyTypeObject Repomd_Type = {
PyObject_HEAD_INIT(NULL)
0, /* ob_size */
0, /* tp_iternext */
repomd_methods, /* tp_methods */
0, /* tp_members */
- 0, /* tp_getset */
+ repomd_getsetters, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
#define RepomdObject_Check(o) PyObject_TypeCheck(o, &Repomd_Type)
+cr_Repomd *Repomd_FromPyObject(PyObject *o);
+
#endif
cr_RepomdRecord *record;
} _RepomdRecordObject;
+PyObject *
+Object_FromRepomdRecord(cr_RepomdRecord *rec)
+{
+ PyObject *py_rec;
+
+ if (!rec) {
+ PyErr_SetString(PyExc_TypeError, "Expected a cr_RepomdRecord pointer not NULL.");
+ return NULL;
+ }
+
+ py_rec = PyObject_CallObject((PyObject *) &RepomdRecord_Type, NULL);
+ cr_repomd_record_free(((_RepomdRecordObject *)py_rec)->record);
+ ((_RepomdRecordObject *)py_rec)->record = rec;
+
+ return py_rec;
+}
+
cr_RepomdRecord *
RepomdRecord_FromPyObject(PyObject *o)
{
{
CR_UNUSED(kwds);
- char *path;
+ char *type = NULL, *path = NULL;
- if (!PyArg_ParseTuple(args, "s|:repomdrecord_init", &path))
+ if (!PyArg_ParseTuple(args, "|zz:repomdrecord_init", &type, &path))
return -1;
/* Free all previous resources when reinitialization */
- if (self->record) {
+ if (self->record)
cr_repomd_record_free(self->record);
- }
/* Init */
- self->record = cr_repomd_record_new(path);
+ self->record = cr_repomd_record_new(type, path);
if (self->record == NULL) {
PyErr_SetString(CrErr_Exception, "RepomdRecord initialization failed");
return -1;
repomdrecord_repr(_RepomdRecordObject *self)
{
CR_UNUSED(self);
- return PyString_FromFormat("<createrepo_c.RepomdRecord object>");
+ if (self->record->type)
+ return PyString_FromFormat("<createrepo_c.RepomdRecord %s object>",
+ self->record->type);
+ else
+ return PyString_FromFormat("<createrepo_c.RepomdRecord object>");
}
/* RepomdRecord methods */
static PyObject *
+copy_repomdrecord(_RepomdRecordObject *self, void *nothing)
+{
+ CR_UNUSED(nothing);
+ if (check_RepomdRecordStatus(self))
+ return NULL;
+ return Object_FromRepomdRecord(cr_repomd_record_copy(self->record));
+}
+
+static PyObject *
fill(_RepomdRecordObject *self, PyObject *args)
{
int checksum_type;
}
static struct PyMethodDef repomdrecord_methods[] = {
+ {"copy", (PyCFunction)copy_repomdrecord, METH_NOARGS, NULL},
{"fill", (PyCFunction)fill, METH_VARARGS, NULL},
{"compress_and_fill", (PyCFunction)compress_and_fill, METH_VARARGS, NULL},
{"rename_file", (PyCFunction)rename_file, METH_NOARGS, NULL},
}
static PyGetSetDef repomdrecord_getsetters[] = {
+ {"type", (getter)get_str, (setter)set_str, NULL, OFFSET(type)},
{"location_real", (getter)get_str, (setter)set_str, NULL, OFFSET(location_real)},
{"location_href", (getter)get_str, (setter)set_str, NULL, OFFSET(location_href)},
{"checksum", (getter)get_str, (setter)set_str, NULL, OFFSET(checksum)},
#include "src/createrepo_c.h"
extern PyTypeObject RepomdRecord_Type;
-cr_RepomdRecord *RepomdRecord_FromPyObject(PyObject *o);
#define RepomdRecordObject_Check(o) PyObject_TypeCheck(o, &RepomdRecord_Type)
+PyObject *Object_FromRepomdRecord(cr_RepomdRecord *rec);
+cr_RepomdRecord *RepomdRecord_FromPyObject(PyObject *o);
+
#endif
#include <Python.h>
#include <assert.h>
#include "typeconversion.h"
+#include "src/createrepo_c.h"
+#include "src/repomd_internal.h"
void
PyErr_ToGError(GError **err)
return NULL;
}
+char *
+PyObject_ToChunkedString(PyObject *pyobj, GStringChunk *chunk)
+{
+ return cr_safe_string_chunk_insert(chunk, PyObject_ToStrOrNull(pyobj));
+}
+
long long
PyObject_ToLongLongOrZero(PyObject *pyobj)
{
return log;
}
+PyObject *
+PyObject_FromDistroTag(cr_DistroTag *tag)
+{
+ PyObject *tuple;
+
+ if ((tuple = PyTuple_New(2)) == NULL)
+ return NULL;
+
+ PyTuple_SetItem(tuple, 0, PyStringOrNone_FromString(tag->cpeid));
+ PyTuple_SetItem(tuple, 1, PyStringOrNone_FromString(tag->val));
+
+ return tuple;
+}
+
+cr_DistroTag *
+PyObject_ToDistroTag(PyObject *tuple, GStringChunk *chunk)
+{
+ PyObject *pyobj;
+ cr_DistroTag *tag = cr_distrotag_new();
+
+ pyobj = PyTuple_GetItem(tuple, 0);
+ tag->cpeid = cr_safe_string_chunk_insert(chunk, PyObject_ToStrOrNull(pyobj));
+
+ pyobj = PyTuple_GetItem(tuple, 2);
+ tag->val = cr_safe_string_chunk_insert(chunk, PyObject_ToStrOrNull(pyobj));
+
+ return tag;
+}
+
GSList *
GSList_FromPyList_Str(PyObject *py_list)
{
PyObject *PyStringOrNone_FromString(const char *str);
char *PyObject_ToStrOrNull(PyObject *pyobj);
+char *PyObject_ToChunkedString(PyObject *pyobj, GStringChunk *chunk);
PyObject *PyObject_FromDependency(cr_Dependency *dep);
cr_Dependency *PyObject_ToDependency(PyObject *tuple, GStringChunk *chunk);
PyObject *PyObject_FromChangelogEntry(cr_ChangelogEntry *log);
cr_ChangelogEntry *PyObject_ToChangelogEntry(PyObject *tuple, GStringChunk *chunk);
+PyObject *PyObject_FromDistroTag(cr_DistroTag *tag);
+cr_DistroTag *PyObject_ToDistroTag(PyObject *tuple, GStringChunk *chunk);
+
GSList *GSList_FromPyList_Str(PyObject *py_list);
#endif
#include "xml_parser-py.h"
#include "typeconversion.h"
#include "package-py.h"
+#include "repomd-py.h"
#include "exception-py.h"
typedef struct {
Py_RETURN_NONE;
}
+
+PyObject *
+py_xml_parse_repomd(PyObject *self, PyObject *args)
+{
+ CR_UNUSED(self);
+
+ char *filename;
+ PyObject *py_repomd, *py_warningcb;
+ CbData cbdata;
+ cr_Repomd *repomd;
+ GError *tmp_err = NULL;
+
+ if (!PyArg_ParseTuple(args, "sOO:py_xml_parse_repomd",
+ &filename,
+ &py_repomd,
+ &py_warningcb)) {
+ return NULL;
+ }
+
+ if (!RepomdObject_Check(py_repomd)) {
+ PyErr_SetString(PyExc_TypeError, "Bad type");
+ return NULL;
+ }
+
+ if (!PyCallable_Check(py_warningcb) && py_warningcb != Py_None) {
+ PyErr_SetString(PyExc_TypeError, "warningcb must be callable or None");
+ return NULL;
+ }
+
+ Py_XINCREF(py_repomd);
+ Py_XINCREF(py_warningcb);
+
+ cr_XmlParserWarningCb ptr_c_warningcb = NULL;
+
+ if (py_warningcb != Py_None)
+ ptr_c_warningcb = c_warningcb;
+
+ cbdata.py_newpkgcb = NULL;
+ cbdata.py_pkgcb = NULL;
+ cbdata.py_warningcb = py_warningcb;
+ cbdata.py_pkg = NULL;
+
+ repomd = Repomd_FromPyObject(py_repomd);
+
+ cr_xml_parse_repomd(filename,
+ repomd,
+ ptr_c_warningcb,
+ &cbdata,
+ &tmp_err);
+
+ Py_XDECREF(py_repomd);
+ Py_XDECREF(py_warningcb);
+
+ if (tmp_err) {
+ PyErr_Format(CrErr_Exception, "%s", tmp_err->message);
+ g_clear_error(&tmp_err);
+ return NULL;
+ }
+
+ Py_RETURN_NONE;
+}
PyObject *py_xml_parse_primary(PyObject *self, PyObject *args);
PyObject *py_xml_parse_filelists(PyObject *self, PyObject *args);
PyObject *py_xml_parse_other(PyObject *self, PyObject *args);
+PyObject *py_xml_parse_repomd(PyObject *self, PyObject *args);
#endif
return (cr_DistroTag *) g_malloc0(sizeof(cr_DistroTag));
}
-void
-cr_distrotag_free(cr_DistroTag *distro)
-{
- if (!distro) return;
- g_free(distro->cpeid);
- g_free(distro->val);
- g_free(distro);
-}
-
-
cr_RepomdRecord *
-cr_repomd_record_new(const char *path)
+cr_repomd_record_new(const char *type, const char *path)
{
cr_RepomdRecord *md = g_malloc0(sizeof(*md));
- md->chunk = g_string_chunk_new(1024);
+ md->chunk = g_string_chunk_new(128);
+ md->type = cr_safe_string_chunk_insert(md->chunk, type);
if (path) {
gchar *filename = cr_get_filename(path);
gchar *location_href = g_strconcat(LOCATION_HREF_PREFIX, filename, NULL);
return md;
}
-
-
void
cr_repomd_record_free(cr_RepomdRecord *md)
{
g_free(md);
}
+cr_RepomdRecord *
+cr_repomd_record_copy(const cr_RepomdRecord *orig)
+{
+ cr_RepomdRecord *rec;
+
+ if (!orig) return NULL;
+
+ rec = cr_repomd_record_new(orig->type, NULL);
+ rec->location_real = cr_safe_string_chunk_insert(rec->chunk,
+ orig->location_real);
+ rec->location_href = cr_safe_string_chunk_insert(rec->chunk,
+ orig->location_href);
+ rec->checksum = cr_safe_string_chunk_insert(rec->chunk,
+ orig->checksum);
+ rec->checksum_type = cr_safe_string_chunk_insert(rec->chunk,
+ orig->checksum_type);
+ rec->checksum_open = cr_safe_string_chunk_insert(rec->chunk,
+ orig->checksum_open);
+ rec->checksum_open_type = cr_safe_string_chunk_insert(rec->chunk,
+ orig->checksum_open_type);
+ rec->timestamp = orig->timestamp;
+ rec->size = orig->size;
+ rec->size_open = orig->size_open;
+ rec->db_ver = orig->db_ver;
+
+ return rec;
+}
contentStat *
cr_get_compressed_content_stat(const char *filename,
return result;
}
-
-
int
cr_repomd_record_fill(cr_RepomdRecord *md,
cr_ChecksumType checksum_type,
return CRE_OK;
}
-
int
cr_repomd_record_compress_and_fill(cr_RepomdRecord *record,
cr_RepomdRecord *crecord,
return CRE_OK;
}
-
int
cr_repomd_record_rename_file(cr_RepomdRecord *md, GError **err)
{
return CRE_OK;
}
-
void
-cr_repomd_dump_data_items(xmlNodePtr root,
- cr_RepomdRecord *md,
- const xmlChar *type)
+cr_repomd_dump_data_items(xmlNodePtr root, cr_RepomdRecord *md)
{
xmlNodePtr data, node;
gchar str_buffer[STR_BUFFER_SIZE];
- if (!root || !md || !type) {
+ if (!root || !md) {
return;
}
data = xmlNewChild(root, NULL, BAD_CAST "data", NULL);
- xmlNewProp(data, BAD_CAST "type", BAD_CAST type);
+ xmlNewProp(data, BAD_CAST "type", BAD_CAST md->type);
node = xmlNewTextChild(data, NULL, BAD_CAST "checksum",
xmlNewChild(data, NULL, BAD_CAST "open-size", BAD_CAST str_buffer);
}
- if (g_str_has_suffix((char *)type, "_db")) {
+ if (g_str_has_suffix((char *)md->type, "_db")) {
g_snprintf(str_buffer, STR_BUFFER_SIZE, "%d", md->db_ver);
xmlNewChild(data, NULL, BAD_CAST "database_version",
BAD_CAST str_buffer);
}
}
-
char *
cr_repomd_xml_dump(cr_Repomd *repomd)
{
xmlDocPtr doc;
xmlNodePtr root;
- GList *keys, *element;
+ GSList *element;
// Start of XML document
// Records
- keys = g_hash_table_get_keys(repomd->records);
- keys = g_list_sort(keys, (GCompareFunc) g_strcmp0);
+ repomd->records = g_slist_sort(repomd->records, (GCompareFunc) g_strcmp0);
- for (element = keys; element; element = g_list_next(element)) {
- char *type = element->data;
- cr_RepomdRecord *rec = g_hash_table_lookup(repomd->records, type);
- cr_repomd_dump_data_items(root, rec, (const xmlChar *) type);
+ for (element = repomd->records; element; element = g_slist_next(element)) {
+ cr_RepomdRecord *rec = element->data;
+ cr_repomd_dump_data_items(root, rec);
}
- g_list_free(keys);
-
// Dump IT!
char *result;
return result;
}
-
cr_Repomd *
cr_repomd_new()
{
cr_Repomd *repomd = g_malloc0(sizeof(cr_Repomd));
- repomd->records = g_hash_table_new_full(g_str_hash,
- g_str_equal,
- g_free,
- (GDestroyNotify) cr_repomd_record_free);
+ repomd->chunk = g_string_chunk_new(0);
return repomd;
}
-
void
cr_repomd_free(cr_Repomd *repomd)
{
if (!repomd) return;
- g_hash_table_destroy(repomd->records);
- cr_slist_free_full(repomd->repo_tags, g_free);
- cr_slist_free_full(repomd->distro_tags, (GDestroyNotify) cr_distrotag_free);
- cr_slist_free_full(repomd->content_tags, g_free);
- g_free(repomd->revision);
+ cr_slist_free_full(repomd->records, (GDestroyNotify) cr_repomd_record_free );
+ g_slist_free(repomd->repo_tags);
+ cr_slist_free_full(repomd->distro_tags, (GDestroyNotify) g_free);
+ g_slist_free(repomd->content_tags);
+ g_string_chunk_free(repomd->chunk);
g_free(repomd);
}
-
void
cr_repomd_set_record(cr_Repomd *repomd,
- cr_RepomdRecord *record,
- const char *type)
+ cr_RepomdRecord *record)
{
if (!repomd || !record) return;
- g_hash_table_replace(repomd->records, g_strdup(type), record);
+ repomd->records = g_slist_append(repomd->records, record);
}
-
void
cr_repomd_set_revision(cr_Repomd *repomd, const char *revision)
{
if (!repomd) return;
- if (repomd->revision) // A revision string already exists
- g_free(repomd->revision);
- repomd->revision = g_strdup(revision);
+ repomd->revision = cr_safe_string_chunk_insert(repomd->chunk, revision);
}
-
void
cr_repomd_add_distro_tag(cr_Repomd *repomd,
const char *cpeid,
cr_DistroTag *distro;
if (!repomd || !tag) return;
distro = cr_distrotag_new();
- distro->cpeid = g_strdup(cpeid);
- distro->val = g_strdup(tag);
+ distro->cpeid = cr_safe_string_chunk_insert(repomd->chunk, cpeid);
+ distro->val = cr_safe_string_chunk_insert(repomd->chunk, tag);
repomd->distro_tags = g_slist_prepend(repomd->distro_tags,
(gpointer) distro);
}
-
void
cr_repomd_add_repo_tag(cr_Repomd *repomd, const char *tag)
{
- if (!repomd) return;
- repomd->repo_tags = g_slist_append(repomd->repo_tags, g_strdup(tag));
+ if (!repomd || !tag) return;
+ repomd->repo_tags = g_slist_append(repomd->repo_tags,
+ cr_safe_string_chunk_insert(repomd->chunk, tag));
}
-
void
cr_repomd_add_content_tag(cr_Repomd *repomd, const char *tag)
{
- if (!repomd) return;
- repomd->content_tags = g_slist_append(repomd->content_tags, g_strdup(tag));
+ if (!repomd || !tag) return;
+ repomd->content_tags = g_slist_append(repomd->content_tags,
+ cr_safe_string_chunk_insert(repomd->chunk, tag));
}
/** Internal representation of cr_RepomdRecord object
*/
typedef struct {
+ char *type; /*!< type of record */
char *location_real; /*!< real path to the file */
char *location_href; /*!< location of the file (in repomd.xml) */
char *checksum; /*!< checksum of file */
long size_open; /*!< size of uncompressed file in bytes */
int db_ver; /*!< version of database */
- GStringChunk *chunk; /*!< string chunk */
+ GStringChunk *chunk; /*!< String chunk */
} cr_RepomdRecord;
/** Distro tag structure
/** Internal representation of cr_Repomd object
*/
typedef struct {
- GHashTable *records; /*!< Hash table with cr_RepomdRecord */
+ gchar *revision; /*!< Revison */
GSList *repo_tags; /*!< List of strings */
- GSList *distro_tags; /*!< List of cr_DistroTag* */
GSList *content_tags; /*!< List of strings */
- gchar *revision;
+ GSList *distro_tags; /*!< List of cr_DistroTag* */
+ GSList *records; /*!< List with cr_RepomdRecords */
+
+ GStringChunk *chunk; /*!< String chunk for repomd strings
+ (Note: RepomdRecord strings are stored
+ in RepomdRecord->chunk) */
} cr_Repomd;
/** Creates (alloc) new cr_RepomdRecord object
+ * @param type Type of record ("primary", "filelists", ..)
* @param path path to the compressed file
*/
-cr_RepomdRecord *cr_repomd_record_new(const char *path);
+cr_RepomdRecord *cr_repomd_record_new(const char *type, const char *path);
/** Destroy cr_RepomdRecord object.
* NOTE: Do NOT use this function on objects attached to cr_Repomd
*/
void cr_repomd_record_free(cr_RepomdRecord *record);
+/** Copy cr_RepomdRecord object.
+ * @param orig cr_RepomdRecord object
+ * @return copy of cr_RepomdRecord object
+ */
+cr_RepomdRecord *cr_repomd_record_copy(const cr_RepomdRecord *orig);
+
/** Fill unfilled items in the cr_RepomdRecord (calculate checksums,
* get file size before/after compression, etc.).
* Note: For groupfile you shoud use cr_repomd_record_compress_and_fill
/** Set cr_Repomd record into cr_Repomd object.
* @param repomd cr_Repomd object
* @param record cr_RepomdRecord object
- * @param type type of record ("primary, "groupfile", ...)
*/
-void cr_repomd_set_record(cr_Repomd *repomd,
- cr_RepomdRecord *record,
- const char *type);
+void cr_repomd_set_record(cr_Repomd *repomd, cr_RepomdRecord *record);
/** Set custom revision string of repomd.
* @param repomd cr_Repomd object
cr_DistroTag *cr_distrotag_new();
-void cr_distrotag_free(cr_DistroTag *distro);
-
#ifdef __cplusplus
}
#endif
tmp_err = NULL;
ret = pd->warningcb(type, warn, pd->warningcb_data, &tmp_err);
+ g_free(warn);
if (ret != CR_CB_RET_OK) {
if (tmp_err)
g_propagate_prefixed_error(&pd->err, tmp_err,
* and ignored by default. But if callback return CR_CB_RET_ERR instead of
* CR_CB_RET_OK then parsing is immediately interrupted.
* @param type Type of warning
- * @param msg Warning msg
+ * @param msg Warning msg. The message is destroyed after the call.
+ * If you want touse the message later, you have to copy it.
* @param cbdata User data.
* @param err GError **
* @return CR_CB_RET_OK (0) or CR_CB_RET_ERR (1) - stops the parsing
assert(pd->repomd);
assert(!pd->repomdrecord);
- pd->repomdrecord = cr_repomd_record_new(NULL);
-
val = cr_find_attr("type", attr);
if (!val) {
cr_xml_parser_warning(pd, CR_XML_WARNING_MISSINGATTR,
val = "unknown";
}
- cr_repomd_set_record(pd->repomd, pd->repomdrecord, val);
+ pd->repomdrecord = cr_repomd_record_new(val, NULL);
+ cr_repomd_set_record(pd->repomd, pd->repomdrecord);
break;
case STATE_LOCATION:
val = cr_find_attr("href", attr);
if (val)
- pd->repomdrecord->location_href = g_strdup(val);
+ pd->repomdrecord->location_href = g_string_chunk_insert(
+ pd->repomdrecord->chunk,
+ val);
else
cr_xml_parser_warning(pd, CR_XML_WARNING_MISSINGATTR,
"Missing attribute \"href\" of a location element");
// val = cr_find_attr("base", attr);
// if (val)
-// pd->repomdrecord->location_base = g_strdup(val);
+// pd->repomdrecord->location_base = g_string_chunk_insert(
+// pd->repodmrecord->chunk,
+// val);
break;
break;
}
- pd->repomdrecord->checksum_type = g_strdup(val);
+ pd->repomdrecord->checksum_type = g_string_chunk_insert(
+ pd->repomdrecord->chunk,
+ val);
break;
case STATE_OPENCHECKSUM:
break;
}
- pd->repomdrecord->checksum_open_type = g_strdup(val);
+ pd->repomdrecord->checksum_open_type = g_string_chunk_insert(
+ pd->repomdrecord->chunk,
+ val);
break;
case STATE_TIMESTAMP:
break;
}
- pd->repomd->revision = g_strdup(pd->content);
+ cr_repomd_set_revision(pd->repomd, pd->content);
break;
case STATE_TAGS:
assert(pd->repomd);
assert(pd->repomdrecord);
- pd->repomdrecord->checksum = g_strdup(pd->content);
+ pd->repomdrecord->checksum = cr_safe_string_chunk_insert(
+ pd->repomdrecord->chunk,
+ pd->content);
break;
case STATE_OPENCHECKSUM:
assert(pd->repomd);
assert(pd->repomdrecord);
- pd->repomdrecord->checksum_open = g_strdup(pd->content);
+ pd->repomdrecord->checksum_open = cr_safe_string_chunk_insert(
+ pd->repomdrecord->chunk,
+ pd->content);
break;
case STATE_TIMESTAMP:
# Test repositories
REPO_00_PATH = os.path.join(REPOS_PATH, "repo_00")
+REPO_00_REPOMD = os.path.join(REPO_00_PATH, "repodata/repomd.xml")
REPO_00_PRIXML = os.path.join(REPO_00_PATH, "repodata/",
"dabe2ce5481d23de1f4f52bdcfee0f9af98316c9e0de2ce8123adeefa0dd08b9-primary.xml.gz")
REPO_00_FILXML = os.path.join(REPO_00_PATH, "repodata/",
"6bf9672d0862e8ef8b8ff05a2fd0208a922b1f5978e6589d87944c88259cb670-other.xml.gz")
REPO_01_PATH = os.path.join(REPOS_PATH, "repo_01")
+REPO_01_REPOMD = os.path.join(REPO_01_PATH, "repodata/repomd.xml")
REPO_01_PRIXML = os.path.join(REPO_01_PATH, "repodata/",
"6c662d665c24de9a0f62c17d8fa50622307739d7376f0d19097ca96c6d7f5e3e-primary.xml.gz")
REPO_01_FILXML = os.path.join(REPO_01_PATH, "repodata/",
"b752a73d9efd4006d740f943db5fb7c2dd77a8324bd99da92e86bd55a2c126ef-other.xml.gz")
REPO_02_PATH = os.path.join(REPOS_PATH, "repo_02")
+REPO_02_REPOMD = os.path.join(REPO_02_PATH, "repodata/repomd.xml")
REPO_02_PRIXML = os.path.join(REPO_02_PATH, "repodata/",
"bcde64b04916a2a72fdc257d61bc922c70b3d58e953499180585f7a360ce86cf-primary.xml.gz")
REPO_02_FILXML = os.path.join(REPO_02_PATH, "repodata/",
shutil.rmtree(self.tmpdir)
def xxx_repomdrecord_fill(self):
- self.assertRaises(TypeError, cr.RepomdRecord)
- self.assertRaises(TypeError, cr.RepomdRecord, None)
-
shutil.copyfile(REPO_00_PRIXML, self.path00)
self.assertTrue(os.path.exists(self.path00))
- rec = cr.RepomdRecord(self.path00)
+ rec = cr.RepomdRecord("primary", self.path00)
self.assertTrue(rec)
rec.fill(cr.SHA256)
rec.rename_file()
# Revision shoud be current Unix time
self.assertTrue(re.search(r"<revision>[0-9]+</revision>", xml))
+ self.assertEqual(md.revision, None)
md.set_revision("foobar")
+ self.assertEqual(md.revision, "foobar")
+ self.assertEqual(md.distro_tags, [])
md.add_distro_tag("tag1")
md.add_distro_tag("tag2", "cpeid1")
md.add_distro_tag("tag3", cpeid="cpeid2")
+ self.assertEqual(md.distro_tags,
+ [('cpeid2', 'tag3'),
+ ('cpeid1', 'tag2'),
+ (None, 'tag1')])
+ self.assertEqual(md.repo_tags, [])
md.add_repo_tag("repotag")
+ self.assertEqual(md.repo_tags, ['repotag'])
+ self.assertEqual(md.content_tags, [])
md.add_content_tag("contenttag")
+ self.assertEqual(md.content_tags, ['contenttag'])
+
+ self.assertEqual(md.records, [])
xml = md.xml_dump()
self.assertEqual(xml,
</repomd>
""")
- rec = cr.RepomdRecord(self.path00)
+ rec = cr.RepomdRecord("primary", self.path00)
rec.fill(cr.SHA256)
rec.timestamp = 1
- md.set_record(rec, "primary")
+ md.set_record(rec)
+
+ self.assertEqual(len(md.records), 1)
xml = md.xml_dump()
self.assertEqual(xml,
shutil.rmtree(self.tmpdir)
def test_repomdrecord_fill(self):
- self.assertRaises(TypeError, cr.RepomdRecord)
- self.assertRaises(TypeError, cr.RepomdRecord, None)
-
shutil.copyfile(REPO_00_PRIXML, self.path00)
self.assertTrue(os.path.exists(self.path00))
- rec = cr.RepomdRecord(self.path00)
+ rec = cr.RepomdRecord("primary", self.path00)
self.assertTrue(rec)
self.assertEqual(rec.location_real, self.path00)
['dabe2ce5481d23de1f4f52bdcfee0f9af98316c9e0de2ce8123adeefa0dd08b9-primary.xml.gz'])
def test_repomdrecord_setters(self):
- self.assertRaises(TypeError, cr.RepomdRecord)
- self.assertRaises(TypeError, cr.RepomdRecord, None)
-
shutil.copyfile(REPO_00_PRIXML, self.path00)
self.assertTrue(os.path.exists(self.path00))
- rec = cr.RepomdRecord(self.path00)
+ rec = cr.RepomdRecord("primary", self.path00)
self.assertTrue(rec)
rec.fill(cr.SHA256)
+ self.assertEqual(rec.type, "primary")
self.assertEqual(rec.location_real, self.path00)
self.assertEqual(rec.location_href, "repodata/primary.xml.gz")
self.assertEqual(rec.checksum, "dabe2ce5481d23de1f4f52bdcfee0f9af98316c9e0de2ce8123adeefa0dd08b9")
# Set new values
+ rec.type = "foo"
rec.location_href = "repodata/foo.xml.gz"
rec.checksum = "foobar11"
rec.checksum_type = "foo1"
# Check
+ self.assertEqual(rec.type, "foo")
self.assertEqual(rec.location_real, self.path00)
self.assertEqual(rec.location_href, "repodata/foo.xml.gz")
self.assertEqual(rec.checksum, "foobar11")
self.assertEqual(rec.db_ver, 11)
def test_repomdrecord_compress_and_fill(self):
- self.assertRaises(TypeError, cr.RepomdRecord)
- self.assertRaises(TypeError, cr.RepomdRecord, None)
-
open(self.path01, "w").write("foobar\ncontent\nhh\n")
self.assertTrue(os.path.exists(self.path01))
- rec = cr.RepomdRecord(self.path01)
+ rec = cr.RepomdRecord("primary", self.path01)
self.assertTrue(rec)
rec_compressed = rec.compress_and_fill(cr.SHA256, cr.GZ_COMPRESSION)
cr.xml_parse_other,
OTHER_MULTI_WARN_00_PATH,
newpkgcb, None, warningcb)
+
+class TestCaseXmlParserRepomd(unittest.TestCase):
+
+ def test_xml_parser_repomd_repo01(self):
+
+ warnings = []
+
+ def warningcb(warn_type, msg):
+ warnings.append((warn_type, msg))
+
+ repomd = cr.Repomd()
+
+ cr.xml_parse_repomd(REPO_01_REPOMD, repomd, warningcb)
+
+ self.assertEqual(warnings, [])
+
+ self.assertEqual(repomd.revision, "1334667230")
+ self.assertEqual(repomd.repo_tags, [])
+ self.assertEqual(repomd.distro_tags, [])
+ self.assertEqual(repomd.content_tags, [])
+ self.assertEqual(len(repomd.records), 3)
+
+ self.assertEqual(repomd.records[0].type, "filelists")
+ self.assertEqual(repomd.records[0].location_real, None)
+ self.assertEqual(repomd.records[0].location_href,
+ "repodata/c7db035d0e6f1b2e883a7fa3229e2d2be70c05a8b8d2b57dbb5f9c1a67483b6c-filelists.xml.gz")
+ self.assertEqual(repomd.records[0].checksum,
+ "c7db035d0e6f1b2e883a7fa3229e2d2be70c05a8b8d2b57dbb5f9c1a67483b6c")
+ self.assertEqual(repomd.records[0].checksum_type, "sha256")
+ self.assertEqual(repomd.records[0].checksum_open,
+ "85bc611be5d81ac8da2fe01e98ef741d243d1518fcc46ada70660020803fbf09")
+ self.assertEqual(repomd.records[0].checksum_open_type, "sha256")
+ self.assertEqual(repomd.records[0].timestamp, 1334667230)
+ self.assertEqual(repomd.records[0].size, 273)
+ self.assertEqual(repomd.records[0].size_open, 389)
+ self.assertEqual(repomd.records[0].db_ver, 0)
+
+ self.assertEqual(repomd.records[1].type, "other")
+ self.assertEqual(repomd.records[1].location_real, None)
+ self.assertEqual(repomd.records[1].location_href,
+ "repodata/b752a73d9efd4006d740f943db5fb7c2dd77a8324bd99da92e86bd55a2c126ef-other.xml.gz")
+ self.assertEqual(repomd.records[1].checksum,
+ "b752a73d9efd4006d740f943db5fb7c2dd77a8324bd99da92e86bd55a2c126ef")
+ self.assertEqual(repomd.records[1].checksum_type, "sha256")
+ self.assertEqual(repomd.records[1].checksum_open,
+ "da6096c924349af0c326224a33be0cdb26897fbe3d25477ac217261652449445")
+ self.assertEqual(repomd.records[1].checksum_open_type, "sha256")
+ self.assertEqual(repomd.records[1].timestamp, 1334667230)
+ self.assertEqual(repomd.records[1].size, 332)
+ self.assertEqual(repomd.records[1].size_open, 530)
+ self.assertEqual(repomd.records[1].db_ver, 0)
+
+ self.assertEqual(repomd.records[2].type, "primary")
+ self.assertEqual(repomd.records[2].location_real, None)
+ self.assertEqual(repomd.records[2].location_href,
+ "repodata/6c662d665c24de9a0f62c17d8fa50622307739d7376f0d19097ca96c6d7f5e3e-primary.xml.gz")
+ self.assertEqual(repomd.records[2].checksum,
+ "6c662d665c24de9a0f62c17d8fa50622307739d7376f0d19097ca96c6d7f5e3e")
+ self.assertEqual(repomd.records[2].checksum_type, "sha256")
+ self.assertEqual(repomd.records[2].checksum_open,
+ "0fc6cadf97d515e87491d24dc9712d8ddaf2226a21ae7f131ff42d71a877c496")
+ self.assertEqual(repomd.records[2].checksum_open_type, "sha256")
+ self.assertEqual(repomd.records[2].timestamp, 1334667230)
+ self.assertEqual(repomd.records[2].size, 782)
+ self.assertEqual(repomd.records[2].size_open, 2085)
+ self.assertEqual(repomd.records[2].db_ver, 0)