Track files per package and add command to list them.
authorKristian Høgsberg <krh@redhat.com>
Wed, 24 Oct 2007 04:05:42 +0000 (00:05 -0400)
committerKristian Høgsberg <krh@redhat.com>
Wed, 24 Oct 2007 04:05:42 +0000 (00:05 -0400)
TODO
bash-completion.sh
main.c
razor.c
razor.h

diff --git a/TODO b/TODO
index b29ac63..eea05b0 100644 (file)
--- a/TODO
+++ b/TODO
@@ -47,3 +47,9 @@
 
 - split out hash table code from importer, make the merger use just
   the hash table.
+
+- try to clean up the
+
+       do { ... } while (((e++)->name & RAZOR_ENTRY_LAST) == 0);
+
+  idiom for iteration of directories.
index b0b0ce8..782f3e9 100644 (file)
@@ -1,6 +1,6 @@
 __razor_commands () {
     local IFS=$'\n'
-    COMPREPLY=($(IFS=: compgen -S' ' -W "list-requires:list-provides:list-files:list-file-packages:what-requires:what-provides:import-yum:import-rpmdb:validate:update:diff" -- $1))
+    COMPREPLY=($(IFS=: compgen -S' ' -W "list-requires:list-provides:list-files:list-file-packages:list-package-files:what-requires:what-provides:import-yum:import-rpmdb:validate:update:diff" -- $1))
 }
 
 __razor_packages () {
@@ -28,7 +28,8 @@ __razor() {
        __razor_commands $cur
     else
        case "${COMP_WORDS[1]}" in
-           list-requires|list-provides) __razor_packages $cur ;;
+           list-requires|list-provides|list-package-files)
+               __razor_packages $cur ;;
            list-files|list-file-packages) __razor_files $cur ;;
            what-requires) __razor_requires $cur ;;
            what-provides) __razor_provides $cur ;;
diff --git a/main.c b/main.c
index eb0c177..48db52e 100644 (file)
--- a/main.c
+++ b/main.c
@@ -74,6 +74,19 @@ command_list_file_packages(int argc, const char *argv[])
        return 0;
 }
 
+static int
+command_list_package_files(int argc, const char *argv[])
+{
+       struct razor_set *set;
+
+       set = razor_set_open(repo_filename);
+       if (set == NULL)
+               return 1;
+       razor_set_list_package_files(set, argv[0]);
+       razor_set_destroy(set);
+
+       return 0;
+}
 
 static int
 command_what_requires(int argc, const char *argv[])
@@ -199,6 +212,7 @@ static struct {
        { "list-provides", "list all provides or provides for the give package", command_list_provides },
        { "list-files", "list files for package set", command_list_files },
        { "list-file-packages", "list packages owning file", command_list_file_packages },
+       { "list-package-files", "list files in package", command_list_package_files },
        { "what-requires", "list the packages that have the given requires", command_what_requires },
        { "what-provides", "list the packages that have the given provides", command_what_provides },
        { "import-yum", "import yum filelist.xml on stdin", command_import_yum },
diff --git a/razor.c b/razor.c
index b6b83c0..dfc567e 100644 (file)
--- a/razor.c
+++ b/razor.c
@@ -35,20 +35,22 @@ struct razor_set_header {
 #define RAZOR_MAGIC 0x7a7a7a7a
 #define RAZOR_VERSION 1
 
-#define RAZOR_PACKAGES 0
-#define RAZOR_REQUIRES 1
-#define RAZOR_PROVIDES 2
-#define RAZOR_STRING_POOL 3
-#define RAZOR_PACKAGE_POOL 4
-#define RAZOR_REQUIRES_POOL 5
-#define RAZOR_PROVIDES_POOL 6
-#define RAZOR_FILE_TREE 7
+#define RAZOR_STRING_POOL 0
+#define RAZOR_PACKAGES 1
+#define RAZOR_REQUIRES 2
+#define RAZOR_PROVIDES 3
+#define RAZOR_FILES 4
+#define RAZOR_PACKAGE_POOL 5
+#define RAZOR_REQUIRES_POOL 6
+#define RAZOR_PROVIDES_POOL 7
+#define RAZOR_FILE_POOL 8
 
 struct razor_package {
        unsigned long name;
        unsigned long version;
        unsigned long requires;
        unsigned long provides;
+       unsigned long files;
 };
 
 struct razor_property {
@@ -59,7 +61,6 @@ struct razor_property {
 
 struct razor_entry {
        unsigned long name;
-       unsigned long count;
        unsigned long start;
        unsigned long packages;
 };
@@ -67,12 +68,13 @@ struct razor_entry {
 struct razor_set {
        struct array string_pool;
        struct array packages;
-       struct array package_pool;
        struct array requires;
        struct array provides;
+       struct array files;
+       struct array package_pool;
        struct array requires_pool;
        struct array provides_pool;
-       struct array file_tree;
+       struct array file_pool;
        struct razor_set_header *header;
 };
 
@@ -170,14 +172,15 @@ zalloc(size_t size)
 }
 
 struct razor_set_section razor_sections[] = {
+       { RAZOR_STRING_POOL,    offsetof(struct razor_set, string_pool) },
        { RAZOR_PACKAGES,       offsetof(struct razor_set, packages) },
        { RAZOR_REQUIRES,       offsetof(struct razor_set, requires) },
        { RAZOR_PROVIDES,       offsetof(struct razor_set, provides) },
-       { RAZOR_STRING_POOL,    offsetof(struct razor_set, string_pool) },
+       { RAZOR_FILES,          offsetof(struct razor_set, files) },
        { RAZOR_PACKAGE_POOL,   offsetof(struct razor_set, package_pool) },
        { RAZOR_REQUIRES_POOL,  offsetof(struct razor_set, requires_pool) },
        { RAZOR_PROVIDES_POOL,  offsetof(struct razor_set, provides_pool) },
-       { RAZOR_FILE_TREE,      offsetof(struct razor_set, file_tree) },
+       { RAZOR_FILE_POOL,      offsetof(struct razor_set, file_pool) },
 };
 
 struct razor_set *
@@ -737,12 +740,15 @@ count_entries(struct import_directory *d)
        }               
 }
 
+#define RAZOR_ENTRY_LAST 0x80000000ul
+#define RAZOR_ENTRY_MASK 0x00fffffful
+
 static void
 serialize_files(struct razor_set *set,
                struct import_directory *d, struct array *array)
 {
        struct import_directory *p, *end;
-       struct razor_entry *e;
+       struct razor_entry *e = NULL;
        unsigned long s;
 
        p = d->files.data;
@@ -751,14 +757,15 @@ serialize_files(struct razor_set *set,
        while (p < end) {
                e = array_add(array, sizeof *e);
                e->name = p->name;
-               e->count = p->files.size / sizeof *p;
-               e->start = s;
+               e->start = p->count > 0 ? s : 0;
                s += p->count;
                e->packages = add_to_property_pool(&set->package_pool,
                                                   &p->packages);
                array_release(&p->packages);
                p++;
        }               
+       if (e != NULL)
+               e->name |= RAZOR_ENTRY_LAST;
 
        p = d->files.data;
        end = d->files.data + d->files.size;
@@ -823,108 +830,48 @@ build_file_tree(struct razor_importer *importer)
        }
 
        count_entries(&root);
-       array_init(&importer->set->file_tree);
+       array_init(&importer->set->files);
 
-       e = array_add(&importer->set->file_tree, sizeof *e);
-       e->name = root.name;
-       e->count = root.files.size / sizeof *d;
+       e = array_add(&importer->set->files, sizeof *e);
+       e->name = root.name | RAZOR_ENTRY_LAST;
        e->start = 1;
+       e->packages = 0;
 
-       serialize_files(importer->set, &root, &importer->set->file_tree);
+       serialize_files(importer->set, &root, &importer->set->files);
 
        array_release(&importer->files);
 }
 
-static const char *
-find_dir(struct razor_set *set, struct razor_entry **dir, const char *pattern)
+static void
+build_package_file_lists(struct razor_set *set)
 {
+       struct razor_package *p, *packages;
+       struct array *pkgs;
        struct razor_entry *e, *end;
-       const char *n, *pool = set->string_pool.data;
-       int len;
+       unsigned long *r, *q;
+       int i, count;
 
-       e = (struct razor_entry *) set->file_tree.data + (*dir)->start;
-       end = e + (*dir)->count;
+       count = set->packages.size / sizeof *p;
+       pkgs = zalloc(count * sizeof *pkgs);
 
+       e = set->files.data;
+       end = set->files.data + set->files.size;
        while (e < end) {
-               n = pool + e->name;
-               len = strlen(n);
-               if (len == 0) {
-                       /* FIXME: Shouldn't have 0-length entries... */
-                       e++;
-                       continue;
-               }
-                       
-               if (strncmp(pattern + 1, n, len) == 0 &&
-                   pattern[len + 1] == '/') {
-                       *dir = e;
-                       return find_dir(set, dir, pattern + len + 1);
+               r = (unsigned long *) set->package_pool.data + e->packages;
+               while (~*r) {
+                       q = array_add(&pkgs[*r++], sizeof *q);
+                       *q = e - (struct razor_entry *) set->files.data;
                }
                e++;
        }
 
-       return pattern + 1;
-}
-
-static void
-list_dir(struct razor_set *set, struct razor_entry *dir,
-        const char *pattern, const char *base)
-{
-       struct razor_entry *e, *end;
-       char *pool = set->string_pool.data;
-
-       e = (struct razor_entry *) set->file_tree.data + dir->start;
-       end = e + dir->count;
-
-       for ( ; e < end; e++) {
-               if (base && base[0] && fnmatch(base, &pool[e->name], 0) != 0)
-                       continue;
-               if (base && pattern)
-                       printf("%.*s%s%s\n",
-                              base - pattern, pattern, pool + e->name,
-                              e->count > 0 ? "/" : "");
-               else
-                       printf("%s%s\n", pool + e->name,
-                              e->count > 0 ? "/" : "");
-               
-       }
-}
-
-void
-razor_set_list_files(struct razor_set *set, const char *pattern)
-{
-       struct razor_entry *e;
-       const char *base;
-
-       if (pattern == NULL)
-               pattern = "/";
-
-       e = set->file_tree.data;
-       base = find_dir(set, &e, pattern);
-       if (base == NULL)
-               return;
-       list_dir(set, e, pattern, base);
-}
-
-void
-razor_set_list_file_packages(struct razor_set *set, const char *filename)
-{
-       struct razor_entry *e;
-       struct razor_package *packages, *p;
-       const char *pool, *base;
-       unsigned long *r;
-
-       e = set->file_tree.data;
-       base = find_dir(set, &e, filename);
-       if (base == NULL)
-               return;
-       
-       r = (unsigned long *) set->package_pool.data + e->packages;
        packages = set->packages.data;
-       pool = set->string_pool.data;
-       while (~*r) {
-               p = &packages[*r++];
-               printf("%s %s\n", &pool[p->name], &pool[p->version]);
+       for (i = 0; i < count; i++) {
+               packages[i].files =
+                       add_to_property_pool(&set->file_pool, &pkgs[i]);
+               array_release(&pkgs[i]);
        }
+       free(pkgs);
 }
 
 struct razor_set *
@@ -958,6 +905,8 @@ razor_importer_finish(struct razor_importer *importer)
        remap_links(&importer->set->package_pool, rmap);
        free(rmap);
 
+       build_package_file_lists(importer->set);
+
        set = importer->set;
        array_release(&importer->buckets);
        free(importer);
@@ -1141,6 +1090,167 @@ razor_set_list_provides_packages(struct razor_set *set,
        razor_set_list_property_packages(set, &set->provides, name, version);
 }
 
+static struct razor_entry *
+find_entry(struct razor_set *set, struct razor_entry *dir, const char *pattern)
+{
+       struct razor_entry *e;
+       const char *n, *pool = set->string_pool.data;
+       int len;
+
+       e = (struct razor_entry *) set->files.data + dir->start;
+       do {
+               n = pool + (e->name & RAZOR_ENTRY_MASK);
+               len = strlen(n);
+               if (len == 0)
+                       /* FIXME: Shouldn't have 0-length entries... */
+                       continue;
+                       
+               if (strcmp(pattern + 1, n) == 0)
+                       return e;
+               if (e->start != 0 && strncmp(pattern + 1, n, len) == 0 &&
+                   pattern[len + 1] == '/') {
+                       return find_entry(set, e, pattern + len + 1);
+               }
+       } while (((e++)->name & RAZOR_ENTRY_LAST) == 0);
+
+       return NULL;
+}
+
+static void
+list_dir(struct razor_set *set, struct razor_entry *dir,
+        const char *prefix, const char *pattern)
+{
+       struct razor_entry *e;
+       const char *n, *pool = set->string_pool.data;
+
+       e = (struct razor_entry *) set->files.data + dir->start;
+       do {
+               n = pool + (e->name & RAZOR_ENTRY_MASK);
+               if (pattern && pattern[0] && fnmatch(pattern, n, 0) != 0)
+                       continue;
+               printf("%s/%s%s\n", prefix, n, e->start > 0 ? "/" : "");
+       } while (((e++)->name & RAZOR_ENTRY_LAST) == 0);
+}
+
+void
+razor_set_list_files(struct razor_set *set, const char *pattern)
+{
+       struct razor_entry *e;
+       char buffer[512], *p, *base;
+
+       if (pattern == NULL)
+               pattern = "/";
+
+       strcpy(buffer, pattern);
+       e = find_entry(set, set->files.data, buffer);
+       if (e && e->start > 0) {
+               base = NULL;
+       } else {
+               p = strrchr(buffer, '/');
+               if (p) {
+                       *p = '\0';
+                       base = p + 1;
+               } else {
+                       base = NULL;
+               }
+       }
+       e = find_entry(set, set->files.data, buffer);
+       if (e->start != 0)
+               list_dir(set, e, buffer, base);
+}
+
+void
+razor_set_list_file_packages(struct razor_set *set, const char *filename)
+{
+       struct razor_entry *e;
+       struct razor_package *packages, *p;
+       const char *pool;
+       unsigned long *r;
+
+       e = find_entry(set, set->files.data, filename);
+       if (e == NULL)
+               return;
+       
+       r = (unsigned long *) set->package_pool.data + e->packages;
+       packages = set->packages.data;
+       pool = set->string_pool.data;
+       while (~*r) {
+               p = &packages[*r++];
+               printf("%s %s\n", &pool[p->name], &pool[p->version]);
+       }
+}
+
+static unsigned long *
+list_package_files(struct razor_set *set, unsigned long *r,
+                  struct razor_entry *dir, unsigned long end,
+                  char *prefix)
+{
+       struct razor_entry *e, *f, *entries;
+       unsigned long next;
+       char *pool;
+       int len;
+       
+       entries = (struct razor_entry *) set->files.data;
+       pool = set->string_pool.data;
+
+       e = entries + dir->start;
+       do {
+               if (entries + *r == e) {
+                       printf("%s/%s\n", prefix,
+                              pool + (e->name & RAZOR_ENTRY_MASK));
+                       r++;
+                       if (*r >= end)
+                               break;
+               }
+       } while (((e++)->name & RAZOR_ENTRY_LAST) == 0);
+
+       e = entries + dir->start;
+       do {
+               if (e->start == 0)
+                       continue;
+
+               if (e->name & RAZOR_ENTRY_LAST)
+                       next = end;
+               else {
+                       f = e + 1; 
+                       while (f->start == 0 && !(f->name & RAZOR_ENTRY_LAST))
+                               f++;
+                       if (f->start == 0)
+                               next = end;
+                       else
+                               next = f->start;
+               }
+
+               if (e->start <= *r && *r < next) {
+                       len = strlen(prefix);
+                       prefix[len] = '/';
+                       strcpy(prefix + len + 1,
+                              pool + (e->name & RAZOR_ENTRY_MASK));
+                       r = list_package_files(set, r, e, next, prefix);
+                       prefix[len] = '\0';
+                       if (*r >= end)
+                               break;
+               }
+       } while (((e++)->name & RAZOR_ENTRY_LAST) == 0);
+
+       return r;
+}
+
+void
+razor_set_list_package_files(struct razor_set *set, const char *name)
+{
+       struct razor_package *package;
+       unsigned long *r, end;
+       char buffer[512];
+
+       package = razor_set_get_package(set, name);
+
+       r = (unsigned long *) set->file_pool.data + package->files;
+       end = set->files.size / sizeof (struct razor_entry);
+       buffer[0] = '\0';
+       list_package_files(set, r, set->files.data, end, buffer);
+}
+
 static void
 razor_set_validate(struct razor_set *set, struct array *unsatisfied)
 {
diff --git a/razor.h b/razor.h
index 09e98f9..4fbafa9 100644 (file)
--- a/razor.h
+++ b/razor.h
@@ -20,6 +20,7 @@ void razor_set_list_provides_packages(struct razor_set *set,
                                      const char *version);
 void razor_set_list_files(struct razor_set *set, const char *prefix);
 void razor_set_list_file_packages(struct razor_set *set, const char *filename);
+void razor_set_list_package_files(struct razor_set *set, const char *name);
 
 void razor_set_list_unsatisfied(struct razor_set *set);
 struct razor_set *razor_set_update(struct razor_set *set,