Support for less/equal/greater version in requires/conflicts, etc
authorDan Winship <danw@gnome.org>
Mon, 4 Feb 2008 19:25:45 +0000 (14:25 -0500)
committerDan Winship <danw@gnome.org>
Mon, 4 Feb 2008 19:25:45 +0000 (14:25 -0500)
Add less/equal/greater information to razor_property, and update
importers and other code.

Move the rpm importer from import.c to rpm.c to avoid code
duplication, and then rename import.c to yum.c since that's all that's
left.

main.c
razor.c
razor.h
rpm.c
test-driver.c
yum.c [moved from import.c with 68% similarity]

diff --git a/main.c b/main.c
index 9e6e5f1..b52fbcb 100644 (file)
--- a/main.c
+++ b/main.c
@@ -14,6 +14,10 @@ static const char *repo_filename = "system.repo";
 static const char *rawhide_repo_filename = "rawhide.repo";
 static const char *updated_repo_filename = "system-updated.repo";
 
+static const char *relations[] = {
+       "<", "<=", "=", ">=", ">"
+};
+
 static int
 command_list(int argc, const char *argv[])
 {
@@ -46,6 +50,7 @@ list_properties(const char *package_name,
        struct razor_property_iterator *pi;
        const char *name, *version;
        enum razor_property_type type;
+       enum razor_version_relation relation;
 
        set = razor_set_open(repo_filename);
        if (package_name)
@@ -55,13 +60,15 @@ list_properties(const char *package_name,
 
        pi = razor_property_iterator_create(set, package);
        while (razor_property_iterator_next(pi, &property,
-                                           &name, &version, &type)) {
+                                           &name, &relation, &version,
+                                           &type)) {
                if (type != required_type)
                        continue;
                if (version[0] == '\0')
                        printf("%s\n", name);
                else
-                       printf("%s-%s\n", name, version);
+                       printf("%s %s %s\n", name, relations[relation],
+                              version);
        }
        razor_property_iterator_destroy(pi);
 
@@ -168,6 +175,7 @@ list_property_packages(const char *ref_name,
        struct razor_property_iterator *pi;
        const char *name, *version;
        enum razor_property_type type;
+       enum razor_version_relation relation;
 
        if (ref_name == NULL)
                return 0;
@@ -178,10 +186,12 @@ list_property_packages(const char *ref_name,
 
        pi = razor_property_iterator_create(set, NULL);
        while (razor_property_iterator_next(pi, &property,
-                                           &name, &version, &type)) {
+                                           &name, &relation, &version,
+                                           &type)) {
                if (strcmp(ref_name, name) != 0)
                        continue;
-               if (ref_version && strcmp(ref_version, version) != 0)
+               if (ref_version && relation == RAZOR_VERSION_EQUAL &&
+                   strcmp(ref_version, version) != 0)
                        continue;
                if (ref_type != type)
                        continue;
diff --git a/razor.c b/razor.c
index 8ff6e92..759819e 100644 (file)
--- a/razor.c
+++ b/razor.c
@@ -58,6 +58,7 @@ struct razor_package {
 
 struct razor_property {
        uint32_t name;
+       uint32_t relation;
        uint32_t version;
        uint32_t packages;
 };
@@ -440,7 +441,9 @@ razor_importer_finish_package(struct razor_importer *importer)
 
 void
 razor_importer_add_property(struct razor_importer *importer,
-                           const char *name, const char *version,
+                           const char *name,
+                           enum razor_version_relation relation,
+                           const char *version,
                            enum razor_property_type type)
 {
        struct razor_property *p;
@@ -448,6 +451,7 @@ razor_importer_add_property(struct razor_importer *importer,
 
        p = array_add(&importer->set->properties, sizeof *p);
        p->name = hashtable_tokenize(&importer->table, name) | (type << 30);
+       p->relation = relation;
        p->version = hashtable_tokenize(&importer->table, version);
        p->packages = importer->package -
                (struct razor_package *) importer->set->packages.data;
@@ -642,10 +646,13 @@ compare_properties(const void *p1, const void *p2, void *data)
        struct razor_set *set = data;
        char *pool = set->string_pool.data;
 
-       if (prop1->name == prop2->name)
-               return versioncmp(&pool[prop1->version],
-                                 &pool[prop2->version]);
-       else if ((prop1->name & RAZOR_ENTRY_MASK) == (prop2->name & RAZOR_ENTRY_MASK))
+       if (prop1->name == prop2->name) {
+               if (prop1->relation == prop2->relation)
+                       return versioncmp(&pool[prop1->version],
+                                         &pool[prop2->version]);
+               else
+                       return prop1->relation - prop2->relation;
+       } else if ((prop1->name & RAZOR_ENTRY_MASK) == (prop2->name & RAZOR_ENTRY_MASK))
                return (prop1->name >> 30) - (prop2->name >> 30);
        else
                return strcmp(&pool[prop1->name & RAZOR_ENTRY_MASK],
@@ -671,9 +678,11 @@ uniqueify_properties(struct razor_set *set)
        rmap = malloc(count * sizeof *map);
        pkgs = zalloc(count * sizeof *pkgs);
        for (rp = set->properties.data, up = rp, i = 0; rp < rp_end; rp++, i++) {
-               if (rp->name != up->name || rp->version != up->version) {
+               if (rp->name != up->name || rp->relation != up->relation ||
+                   rp->version != up->version) {
                        up++;
                        up->name = rp->name;
+                       up->relation = rp->relation;
                        up->version = rp->version;
                }
 
@@ -1061,7 +1070,9 @@ razor_property_iterator_create(struct razor_set *set,
 int
 razor_property_iterator_next(struct razor_property_iterator *pi,
                             struct razor_property **property,
-                            const char **name, const char **version,
+                            const char **name,
+                            enum razor_version_relation *relation,
+                            const char **version,
                             enum razor_property_type *type)
 {
        char *pool;
@@ -1082,6 +1093,7 @@ razor_property_iterator_next(struct razor_property_iterator *pi,
                pool = pi->set->string_pool.data;
                *property = p;
                *name = &pool[p->name & RAZOR_ENTRY_MASK];
+               *relation = p->relation;
                *version = &pool[p->version];
                *type = p->name >> 30;
        } else {
@@ -1443,12 +1455,14 @@ merge_packages(struct razor_merger *merger, struct array *packages)
 
 static uint32_t
 add_property(struct razor_merger *merger,
-            const char *name, const char *version, int type)
+            const char *name, enum razor_version_relation relation,
+            const char *version, int type)
 {
        struct razor_property *p;
 
        p = array_add(&merger->set->properties, sizeof *p);
        p->name = hashtable_tokenize(&merger->table, name) | (type << 30);
+       p->relation = relation;
        p->version = hashtable_tokenize(&merger->table, version);
 
        return p - (struct razor_property *) merger->set->properties.data;
@@ -1494,21 +1508,26 @@ merge_properties(struct razor_merger *merger)
                else
                        cmp = 1;
                if (cmp == 0)
+                       cmp = p1->relation - p2->relation;
+               if (cmp == 0)
                        cmp = versioncmp(&pool1[p1->version],
                                         &pool2[p2->version]);
                if (cmp < 0) {
                        map1[i++] = add_property(merger,
                                                 &pool1[p1->name & RAZOR_ENTRY_MASK],
+                                                p1->relation,
                                                 &pool1[p1->version],
                                                 (p1->name >> 30));
                } else if (cmp > 0) {
                        map2[j++] = add_property(merger,
                                                 &pool2[p2->name & RAZOR_ENTRY_MASK],
+                                                p2->relation,
                                                 &pool2[p2->version],
                                                 (p2->name >> 30));
                } else  {
                        map1[i++] = map2[j++] = add_property(merger,
                                                             &pool1[p1->name & RAZOR_ENTRY_MASK],
+                                                            p1->relation,
                                                             &pool1[p1->version],
                                                             (p1->name >> 30));
                }
diff --git a/razor.h b/razor.h
index edd9351..6ecd950 100644 (file)
--- a/razor.h
+++ b/razor.h
@@ -14,6 +14,14 @@ enum razor_property_type {
        RAZOR_PROPERTY_OBSOLETES
 };
 
+enum razor_version_relation {
+       RAZOR_VERSION_LESS,
+       RAZOR_VERSION_LESS_OR_EQUAL,
+       RAZOR_VERSION_EQUAL,
+       RAZOR_VERSION_GREATER_OR_EQUAL,
+       RAZOR_VERSION_GREATER
+};
+
 struct razor_set *razor_set_create(void);
 struct razor_set *razor_set_open(const char *filename);
 void razor_set_destroy(struct razor_set *set);
@@ -43,7 +51,9 @@ razor_property_iterator_create(struct razor_set *set,
                               struct razor_package *package);
 int razor_property_iterator_next(struct razor_property_iterator *pi,
                                 struct razor_property **property,
-                                const char **name, const char **version,
+                                const char **name,
+                                enum razor_version_relation *relation,
+                                const char **version,
                                 enum razor_property_type *type);
 void
 razor_property_iterator_destroy(struct razor_property_iterator *pi);
@@ -76,7 +86,9 @@ void razor_importer_destroy(struct razor_importer *importer);
 void razor_importer_begin_package(struct razor_importer *importer,
                                const char *name, const char *version);
 void razor_importer_add_property(struct razor_importer *importer,
-                                const char *name, const char *version,
+                                const char *name,
+                                enum razor_version_relation relation,
+                                const char *version,
                                 enum razor_property_type type);
 void razor_importer_add_file(struct razor_importer *importer,
                             const char *name);
diff --git a/rpm.c b/rpm.c
index 3b3a01b..5091afc 100644 (file)
--- a/rpm.c
+++ b/rpm.c
@@ -9,6 +9,7 @@
 #include <unistd.h>
 #include <arpa/inet.h>
 #include <rpm/rpmlib.h>
+#include <rpm/rpmdb.h>
 #include <zlib.h>
 
 #include "razor.h"
@@ -73,22 +74,47 @@ razor_rpm_get_indirect(struct razor_rpm *rpm,
        return NULL;
 }
 
+static enum razor_version_relation
+rpm_to_razor_flags (uint_32 flags)
+{
+       switch (flags & (RPMSENSE_LESS | RPMSENSE_EQUAL | RPMSENSE_GREATER)) {
+       case RPMSENSE_LESS:
+               return RAZOR_VERSION_LESS;
+       case RPMSENSE_LESS|RPMSENSE_EQUAL:
+               return RAZOR_VERSION_LESS_OR_EQUAL;
+       case RPMSENSE_EQUAL:
+               return RAZOR_VERSION_EQUAL;
+       case RPMSENSE_GREATER|RPMSENSE_EQUAL:
+               return RAZOR_VERSION_GREATER_OR_EQUAL;
+       case RPMSENSE_GREATER:
+               return RAZOR_VERSION_GREATER;
+       }
+
+       /* FIXME? */
+       return RAZOR_VERSION_EQUAL;
+}
+
 static void
 import_properties(struct razor_importer *importer, unsigned long type,
                  struct razor_rpm *rpm,
                  int name_tag, int version_tag, int flags_tag)
 {
        const char *name, *version;
+       uint_32 flags;
        unsigned int i, count;
 
        name = razor_rpm_get_indirect(rpm, name_tag, &count);
        if (name == NULL)
                return;
 
+       flags = *(uint_32 *)razor_rpm_get_indirect(rpm, flags_tag, &count);
+
        /* FIXME: Concat version and release. */
        version = razor_rpm_get_indirect(rpm, version_tag, &count);
        for (i = 0; i < count; i++) {
-               razor_importer_add_property(importer, name, version, type);
+               razor_importer_add_property(importer, name,
+                                           rpm_to_razor_flags (flags),
+                                           version, type);
                name += strlen(name) + 1;
                version += strlen(version) + 1;
        }
@@ -534,3 +560,101 @@ razor_importer_add_rpm(struct razor_importer *importer, struct razor_rpm *rpm)
 
        return 0;
 }
+
+union rpm_entry {
+       void *p;
+       char *string;
+       char **list;
+       uint_32 *flags;
+};
+
+static void
+add_properties(struct razor_importer *importer,
+              enum razor_property_type property_type,
+              Header h, int_32 name_tag, int_32 version_tag, int_32 flags_tag)
+{
+       union rpm_entry names, versions, flags;
+       int_32 i, type, count;
+
+       headerGetEntry(h, name_tag, &type, &names.p, &count);
+       headerGetEntry(h, version_tag, &type, &versions.p, &count);
+       headerGetEntry(h, flags_tag, &type, &flags.p, &count);
+
+       for (i = 0; i < count; i++)
+               razor_importer_add_property(importer,
+                                           names.list[i],
+                                           rpm_to_razor_flags (flags.flags[i]),
+                                           versions.list[i],
+                                           property_type);
+}
+
+struct razor_set *
+razor_set_create_from_rpmdb(void)
+{
+       struct razor_importer *importer;
+       rpmdbMatchIterator iter;
+       Header h;
+       int_32 type, count, i;
+       union rpm_entry name, version, release;
+       union rpm_entry basenames, dirnames, dirindexes;
+       char filename[PATH_MAX];
+       rpmdb db;
+
+       rpmReadConfigFiles(NULL, NULL);
+
+       if (rpmdbOpen("", &db, O_RDONLY, 0644) != 0) {
+               fprintf(stderr, "cannot open rpm database\n");
+               exit(1);
+       }
+
+       importer = razor_importer_new();
+
+       iter = rpmdbInitIterator(db, 0, NULL, 0);
+       while (h = rpmdbNextIterator(iter), h != NULL) {
+               headerGetEntry(h, RPMTAG_NAME, &type, &name.p, &count);
+               headerGetEntry(h, RPMTAG_VERSION, &type, &version.p, &count);
+               headerGetEntry(h, RPMTAG_RELEASE, &type, &release.p, &count);
+               snprintf(filename, sizeof filename, "%s-%s",
+                        version.string, release.string);
+               razor_importer_begin_package(importer, name.string, filename);
+
+               add_properties(importer, RAZOR_PROPERTY_REQUIRES, h,
+                              RPMTAG_REQUIRENAME,
+                              RPMTAG_REQUIREVERSION,
+                              RPMTAG_REQUIREFLAGS);
+
+               add_properties(importer, RAZOR_PROPERTY_PROVIDES, h,
+                              RPMTAG_PROVIDENAME,
+                              RPMTAG_PROVIDEVERSION,
+                              RPMTAG_PROVIDEFLAGS);
+
+               add_properties(importer, RAZOR_PROPERTY_OBSOLETES, h,
+                              RPMTAG_OBSOLETENAME,
+                              RPMTAG_OBSOLETEVERSION,
+                              RPMTAG_OBSOLETEFLAGS);
+
+               add_properties(importer, RAZOR_PROPERTY_CONFLICTS, h,
+                              RPMTAG_CONFLICTNAME,
+                              RPMTAG_CONFLICTVERSION,
+                              RPMTAG_CONFLICTFLAGS);
+
+               headerGetEntry(h, RPMTAG_BASENAMES, &type,
+                              &basenames.p, &count);
+               headerGetEntry(h, RPMTAG_DIRNAMES, &type,
+                              &dirnames.p, &count);
+               headerGetEntry(h, RPMTAG_DIRINDEXES, &type,
+                              &dirindexes.p, &count);
+               for (i = 0; i < count; i++) {
+                       snprintf(filename, sizeof filename, "%s%s",
+                                dirnames.list[dirindexes.flags[i]],
+                                basenames.list[i]);
+                       razor_importer_add_file(importer, filename);
+               }
+
+               razor_importer_finish_package(importer);
+       }
+
+       rpmdbClose(db);
+
+       return razor_importer_finish(importer);
+}
index 6eb40f5..5fbdc40 100644 (file)
@@ -95,7 +95,8 @@ parse_property(struct test_context *ctx, const char **atts,
                exit(-1);
        }
        
-       razor_importer_add_property(ctx->importer, name, version, type);
+       razor_importer_add_property(ctx->importer, name,
+                                   RAZOR_VERSION_EQUAL, version, type);
 }
 
 static void
@@ -190,6 +191,7 @@ verify_end(struct test_context *ctx)
        struct razor_property *property;
        const char *name, *version;
        enum razor_property_type type;
+       enum razor_version_relation relation;
 
        if (ctx->package_iterator != NULL) {
                if (razor_package_iterator_next(ctx->package_iterator,
@@ -206,7 +208,8 @@ verify_end(struct test_context *ctx)
        if (ctx->property_iterator != NULL) {
                if (razor_property_iterator_next(ctx->property_iterator,
                                                 &property,
-                                                &name, &version, &type)) {
+                                                &name, &relation, &version,
+                                                &type)) {
                        fprintf(stderr, "too few properties in set\n");
                        exit(-1);
                }
@@ -251,6 +254,7 @@ verify_property(struct test_context *ctx,
        struct razor_property *property;
        const char *name, *version, *ref_name, *ref_version;
        enum razor_property_type type;
+       enum razor_version_relation relation;
        int same_version;
 
        if (ctx->property_iterator == NULL) {
@@ -262,7 +266,7 @@ verify_property(struct test_context *ctx,
 
        get_atts(atts, "name", &ref_name, "eq", &ref_version, NULL);
        if (!razor_property_iterator_next(ctx->property_iterator, &property,
-                                         &name, &version, &type)) {
+                                         &name, &relation, &version, &type)) {
                fprintf(stderr, "too many properties in set\n");
                exit(-1);
        }
diff --git a/import.c b/yum.c
similarity index 68%
rename from import.c
rename to yum.c
index 68e0a73..8937077 100644 (file)
--- a/import.c
+++ b/yum.c
@@ -10,8 +10,6 @@
 
 #include <expat.h>
 #include <zlib.h>
-#include <rpm/rpmlib.h>
-#include <rpm/rpmdb.h>
 #include "razor.h"
 
 /* Import a yum filelist as a razor package set. */
@@ -39,11 +37,32 @@ struct yum_context {
        int state;
 };
 
+static enum razor_version_relation
+yum_to_razor_flags (const char *flags)
+{
+       /* FIXME? */
+       if (!flags)
+               return RAZOR_VERSION_EQUAL;
+
+       if (flags[0] == 'L') {
+               if (flags[1] == 'T')
+                       return RAZOR_VERSION_LESS;
+               else
+                       return RAZOR_VERSION_LESS_OR_EQUAL;
+       } else if (flags[0] == 'G') {
+               if (flags[1] == 'T')
+                       return RAZOR_VERSION_GREATER;
+               else
+                       return RAZOR_VERSION_GREATER_OR_EQUAL;
+       } else
+               return RAZOR_VERSION_EQUAL;
+}
+
 static void
 yum_primary_start_element(void *data, const char *name, const char **atts)
 {
        struct yum_context *ctx = data;
-       const char *n, *version, *release;
+       const char *n, *version, *release, *flags;
        char buffer[128];
        int i;
 
@@ -83,6 +102,7 @@ yum_primary_start_element(void *data, const char *name, const char **atts)
                n = NULL;
                version = NULL;
                release = NULL;
+               flags = NULL;
                for (i = 0; atts[i]; i += 2) {
                        if (strcmp(atts[i], "name") == 0)
                                n = atts[i + 1];
@@ -90,6 +110,8 @@ yum_primary_start_element(void *data, const char *name, const char **atts)
                                version = atts[i + 1];
                        else if (strcmp(atts[i], "rel") == 0)
                                release = atts[i + 1];
+                       else if (strcmp(atts[i], "flags") == 0)
+                               flags = atts[i + 1];
                }
 
                if (n == NULL) {
@@ -108,19 +130,27 @@ yum_primary_start_element(void *data, const char *name, const char **atts)
                        
                switch (ctx->state) {
                case YUM_STATE_REQUIRES:
-                       razor_importer_add_property(ctx->importer, n, buffer,
+                       razor_importer_add_property(ctx->importer, n,
+                                                   yum_to_razor_flags (flags),
+                                                   buffer,
                                                    RAZOR_PROPERTY_REQUIRES);
                        break;
                case YUM_STATE_PROVIDES:
-                       razor_importer_add_property(ctx->importer, n, buffer,
+                       razor_importer_add_property(ctx->importer, n,
+                                                   yum_to_razor_flags (flags),
+                                                   buffer,
                                                    RAZOR_PROPERTY_PROVIDES);
                        break;
                case YUM_STATE_OBSOLETES:
-                       razor_importer_add_property(ctx->importer, n, buffer,
+                       razor_importer_add_property(ctx->importer, n,
+                                                   yum_to_razor_flags (flags),
+                                                   buffer,
                                                    RAZOR_PROPERTY_OBSOLETES);
                        break;
                case YUM_STATE_CONFLICTS:
-                       razor_importer_add_property(ctx->importer, n, buffer,
+                       razor_importer_add_property(ctx->importer, n,
+                                                   yum_to_razor_flags (flags),
+                                                   buffer,
                                                    RAZOR_PROPERTY_CONFLICTS);
                        break;
                }
@@ -280,100 +310,3 @@ razor_set_create_from_yum(void)
 
        return razor_importer_finish(ctx.importer);
 }
-
-union rpm_entry {
-       void *p;
-       char *string;
-       char **list;
-       unsigned int *flags;
-};
-
-static void
-add_properties(struct razor_importer *importer,
-              enum razor_property_type property_type,
-              Header h, int_32 name_tag, int_32 version_tag, int_32 flags_tag)
-{
-       union rpm_entry names, versions, flags;
-       int_32 i, type, count;
-
-       headerGetEntry(h, name_tag, &type, &names.p, &count);
-       headerGetEntry(h, version_tag, &type, &versions.p, &count);
-       headerGetEntry(h, flags_tag, &type, &flags.p, &count);
-
-       for (i = 0; i < count; i++)
-               razor_importer_add_property(importer,
-                                           names.list[i],
-                                           versions.list[i],
-                                           property_type);
-}
-
-struct razor_set *
-razor_set_create_from_rpmdb(void)
-{
-       struct razor_importer *importer;
-       rpmdbMatchIterator iter;
-       Header h;
-       int_32 type, count, i;
-       union rpm_entry name, version, release;
-       union rpm_entry basenames, dirnames, dirindexes;
-       char filename[PATH_MAX];
-       rpmdb db;
-
-       rpmReadConfigFiles(NULL, NULL);
-
-       if (rpmdbOpen("", &db, O_RDONLY, 0644) != 0) {
-               fprintf(stderr, "cannot open rpm database\n");
-               exit(1);
-       }
-
-       importer = razor_importer_new();
-
-       iter = rpmdbInitIterator(db, 0, NULL, 0);
-       while (h = rpmdbNextIterator(iter), h != NULL) {
-               headerGetEntry(h, RPMTAG_NAME, &type, &name.p, &count);
-               headerGetEntry(h, RPMTAG_VERSION, &type, &version.p, &count);
-               headerGetEntry(h, RPMTAG_RELEASE, &type, &release.p, &count);
-               snprintf(filename, sizeof filename, "%s-%s",
-                        version.string, release.string);
-               razor_importer_begin_package(importer, name.string, filename);
-
-               add_properties(importer, RAZOR_PROPERTY_REQUIRES, h,
-                              RPMTAG_REQUIRENAME,
-                              RPMTAG_REQUIREVERSION,
-                              RPMTAG_REQUIREFLAGS);
-
-               add_properties(importer, RAZOR_PROPERTY_PROVIDES, h,
-                              RPMTAG_PROVIDENAME,
-                              RPMTAG_PROVIDEVERSION,
-                              RPMTAG_PROVIDEFLAGS);
-
-               add_properties(importer, RAZOR_PROPERTY_OBSOLETES, h,
-                              RPMTAG_OBSOLETENAME,
-                              RPMTAG_OBSOLETEVERSION,
-                              RPMTAG_OBSOLETEFLAGS);
-
-               add_properties(importer, RAZOR_PROPERTY_CONFLICTS, h,
-                              RPMTAG_CONFLICTNAME,
-                              RPMTAG_CONFLICTVERSION,
-                              RPMTAG_CONFLICTFLAGS);
-
-               headerGetEntry(h, RPMTAG_BASENAMES, &type,
-                              &basenames.p, &count);
-               headerGetEntry(h, RPMTAG_DIRNAMES, &type,
-                              &dirnames.p, &count);
-               headerGetEntry(h, RPMTAG_DIRINDEXES, &type,
-                              &dirindexes.p, &count);
-               for (i = 0; i < count; i++) {
-                       snprintf(filename, sizeof filename, "%s%s",
-                                dirnames.list[dirindexes.flags[i]],
-                                basenames.list[i]);
-                       razor_importer_add_file(importer, filename);
-               }
-
-               razor_importer_finish_package(importer);
-       }
-
-       rpmdbClose(db);
-
-       return razor_importer_finish(importer);
-}