[Yum-devel] [PATCH 4/5] Add xml parsing for filelists delta files

James Bowes jbowes at redhat.com
Mon Jun 11 12:16:34 UTC 2007


The xml format is similar to that of primary-delta, replacing the
contents of '<additions>' with xml of the format found in filelists.xml
---
 delta-parser.c |    8 ++-
 xml-parser.c   |  178 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 xml-parser.h   |    8 +++
 3 files changed, 192 insertions(+), 2 deletions(-)

diff --git a/delta-parser.c b/delta-parser.c
index 52dafbf..c67ebe8 100644
--- a/delta-parser.c
+++ b/delta-parser.c
@@ -28,11 +28,15 @@ int main(int argc, char* argv[])
         return -1;
     }
 
-    if (!strcmp ("primary", argv[1]))
+    if (!strcmp ("primary", argv[1])) {
         yum_xml_parse_primary_delta (argv[2], count_callback,
                                      addition_callback, removal_callback,
                                      NULL, &err);
-    else {
+    } else if (!strcmp ("filelists", argv[1])) {
+        yum_xml_parse_filelists_delta (argv[2], count_callback,
+                                       addition_callback, removal_callback,
+                                       NULL, &err);
+    } else {
         printf ("unknown metadata type '%s'\n", argv[1]);
         return -1;
     }
diff --git a/xml-parser.c b/xml-parser.c
index 7668c48..4e3900f 100644
--- a/xml-parser.c
+++ b/xml-parser.c
@@ -1027,6 +1027,184 @@ yum_xml_parse_filelists (const char *filename,
     g_string_free (sctx.text_buffer, TRUE);
 }
 
+typedef struct {
+    FilelistSAXContext pctx;
+    DeltaSAXContextState state;
+    PackageFn package_removal_fn;
+} FilelistDeltaSAXContext;
+
+static void
+filelist_delta_parser_toplevel_start (FilelistDeltaSAXContext *ctx,
+                                     const char *name,
+                                     const char **attrs)
+{
+    SAXContext *sctx = &(&ctx->pctx)->sctx;
+
+    if (!strcmp (name, "additions")) {
+        ctx->state = DELTA_PARSER_ADDITIONS;
+    }
+    else if (!strcmp (name, "removals")) {
+        ctx->state = DELTA_PARSER_REMOVALS;
+    }
+
+    else if (sctx->count_fn && !strcmp (name, "filelists")) {
+        int i;
+        const char *attr;
+        const char *value;
+
+        for (i = 0; attrs && attrs[i]; i++) {
+            attr = attrs[i];
+            value = attrs[++i];
+
+            if (!strcmp (attr, "packages")) {
+                sctx->count_fn (string_to_guint32_with_default (value, 0),
+                               sctx->user_data);
+                break;
+            }
+        }
+    }
+}
+
+static void
+filelist_delta_sax_start_element (void *data, const char *name,
+                                 const char **attrs)
+{
+    FilelistDeltaSAXContext *ctx = (FilelistDeltaSAXContext *) data;
+    SAXContext *sctx = &(&ctx->pctx)->sctx;
+
+    if (sctx->text_buffer->len)
+        g_string_truncate (sctx->text_buffer, 0);
+
+    switch (ctx->state) {
+    case DELTA_PARSER_TOPLEVEL:
+        filelist_delta_parser_toplevel_start (ctx, name, attrs);
+        break;
+    case DELTA_PARSER_REMOVALS:
+        delta_parser_removals_start (sctx, name, attrs);
+        break;
+    case DELTA_PARSER_ADDITIONS:
+        filelist_sax_start_element (&ctx->pctx, name, attrs);
+        break;
+    default:
+        break;
+    }
+}
+
+static void
+filelist_delta_parser_removals_end (FilelistDeltaSAXContext *ctx,
+                                   const char *name)
+{
+    if (!strcmp (name, "package")) {
+        SAXContext *sctx = &(&ctx->pctx)->sctx;
+
+        Package *p = sctx->current_package;
+        g_assert (p != NULL);
+
+        if (ctx->package_removal_fn && !*sctx->error)
+            ctx->package_removal_fn (p, sctx->user_data);
+
+        package_free (p);
+        sctx->current_package = NULL;
+
+        sctx->want_text = FALSE;
+    }
+    else if (!strcmp (name, "removals")) {
+        ctx->state = DELTA_PARSER_TOPLEVEL;
+    }
+}
+
+static void
+filelist_delta_sax_end_element (void *data, const char *name)
+{
+    FilelistDeltaSAXContext *ctx = (FilelistDeltaSAXContext *) data;
+    SAXContext *sctx = &(&ctx->pctx)->sctx;
+
+    switch (ctx->state) {
+    case DELTA_PARSER_ADDITIONS:
+        if (ctx->pctx.state == FILELIST_PARSER_TOPLEVEL) {
+            if (!strcmp (name, "additions"))
+                ctx->state = DELTA_PARSER_TOPLEVEL;
+        }
+        else
+            filelist_sax_end_element (&ctx->pctx, name);
+        break;
+    case DELTA_PARSER_REMOVALS:
+        filelist_delta_parser_removals_end (ctx, name);
+        break;
+    default:
+        break;
+    }
+
+    g_string_truncate (sctx->text_buffer, 0);
+}
+
+static xmlSAXHandler filelist_delta_sax_handler = {
+    NULL,      /* internalSubset */
+    NULL,      /* isStandalone */
+    NULL,      /* hasInternalSubset */
+    NULL,      /* hasExternalSubset */
+    NULL,      /* resolveEntity */
+    NULL,      /* getEntity */
+    NULL,      /* entityDecl */
+    NULL,      /* notationDecl */
+    NULL,      /* attributeDecl */
+    NULL,      /* elementDecl */
+    NULL,      /* unparsedEntityDecl */
+    NULL,      /* setDocumentLocator */
+    NULL,      /* startDocument */
+    NULL,      /* endDocument */
+    (startElementSAXFunc) filelist_delta_sax_start_element, /* startElement */
+    (endElementSAXFunc) filelist_delta_sax_end_element,     /* endElement */
+    NULL,      /* reference */
+    (charactersSAXFunc) sax_characters,      /* characters */
+    NULL,      /* ignorableWhitespace */
+    NULL,      /* processingInstruction */
+    NULL,      /* comment */
+    sax_warning,      /* warning */
+    sax_error,      /* error */
+    sax_error,      /* fatalError */
+};
+
+void
+yum_xml_parse_filelists_delta (const char *filename,
+                              CountFn count_callback,
+                              PackageFn package_addition_callback,
+                              PackageFn package_removal_callback,
+                              gpointer user_data,
+                              GError **err)
+{
+    FilelistDeltaSAXContext ctx;
+    FilelistSAXContext pctx;
+    SAXContext sctx;
+    int rc;
+
+    sctx.md_type = "filelists-delta.xml";
+    sctx.error = err;
+    sctx.count_fn = count_callback;
+    sctx.package_fn = package_addition_callback;
+    sctx.user_data = user_data;
+    sctx.current_package = NULL;
+    sctx.want_text = FALSE;
+    sctx.text_buffer = g_string_sized_new (PACKAGE_FIELD_SIZE);
+
+    pctx.current_file = NULL;
+    pctx.state = FILELIST_PARSER_TOPLEVEL;
+    pctx.sctx = sctx;
+
+    ctx.state = DELTA_PARSER_TOPLEVEL;
+    ctx.package_removal_fn = package_removal_callback;
+    ctx.pctx = pctx;
+
+    xmlSubstituteEntitiesDefault (1);
+    rc = xmlSAXUserParseFile (&filelist_delta_sax_handler, &ctx, filename);
+
+    if (sctx.current_package) {
+        g_warning ("Incomplete package lost");
+        package_free (sctx.current_package);
+    }
+
+    g_string_free (sctx.text_buffer, TRUE);
+}
 /*****************************************************************************/
 
 typedef enum {
diff --git a/xml-parser.h b/xml-parser.h
index 6461628..29cc423 100644
--- a/xml-parser.h
+++ b/xml-parser.h
@@ -46,6 +46,14 @@ yum_xml_parse_filelists (const char *filename,
                          gpointer user_data,
                          GError **err);
 
+void yum_xml_parse_filelists_delta (const char *filename,
+                                    CountFn count_callback,
+                                    PackageFn package_addition_callback,
+                                    PackageFn package_removal_callback,
+                                    gpointer user_data,
+                                    GError **err);
+
+
 void yum_xml_parse_other (const char *filename,
                           CountFn count_callback,
                           PackageFn package_callback,
-- 
1.5.2.1.938.gac3b4




More information about the Yum-devel mailing list