Add basic support for uninstall scripts.
authorJ. Ali Harlow <ali@juiblex.co.uk>
Fri, 12 Jun 2009 15:59:11 +0000 (16:59 +0100)
committerJ. Ali Harlow <ali@juiblex.co.uk>
Fri, 12 Jun 2009 15:59:11 +0000 (16:59 +0100)
RPM_INSTALL_PREFIX{n} is not yet supported and upgrading a package
where an uninstall script changes may need more work to ensure the
old script doesn't get included in the merged set (when it is too
late to remove). I haven't yet tested whether this is a real problem.

13 files changed:
librazor/importer.c
librazor/merger.c
librazor/razor-internal.h
librazor/razor.c
librazor/razor.h
librazor/rpm.c
librazor/transaction.c
src/import-rpmdb.c
src/main.c
src/rpm.c
src/test-driver.c
test/remove.sh
test/zip.spec

index 2b1a0e1..bb4695a 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
  * Copyright (C) 2008  Red Hat, Inc
+ * Copyright (C) 2009  J. Ali Harlow <ali@juiblex.co.uk>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -82,6 +83,7 @@ razor_importer_begin_package(struct razor_importer *importer,
                             const char *version,
                             const char *arch)
 {
+       uint32_t empty;
        struct razor_package *p;
 
        p = array_add(&importer->set->packages, sizeof *p);
@@ -92,6 +94,12 @@ razor_importer_begin_package(struct razor_importer *importer,
 
        importer->package = p;
        array_init(&importer->properties);
+
+       empty = hashtable_tokenize(&importer->details_table, "");
+       importer->package->preun.program = empty;
+       importer->package->preun.body = empty;
+       importer->package->postun.program = empty;
+       importer->package->postun.body = empty;
 }
 
 /**
@@ -135,6 +143,39 @@ razor_importer_add_details(struct razor_importer *importer,
 }
 
 /**
+ * razor_importer_add_script:
+ * @importer: the %razor_importer
+ * @script: either %RAZOR_PROPERTY_PREUN or %RAZOR_PROPERTY_POSTUN
+ * @program: the program to run the script
+ * @body: the body of the script
+ *
+ * Provide a script to use when uninstalling the current package.
+ **/
+RAZOR_EXPORT void
+razor_importer_add_script(struct razor_importer *importer,
+                         enum razor_property_flags script,
+                         const char *program,
+                         const char *body)
+{
+       switch (script) {
+       case RAZOR_PROPERTY_PREUN:
+               importer->package->preun.program =
+                       hashtable_tokenize(&importer->table, program);
+               importer->package->preun.body =
+                       hashtable_tokenize(&importer->table, body);
+               break;
+       case RAZOR_PROPERTY_POSTUN:
+               importer->package->postun.program =
+                       hashtable_tokenize(&importer->table, program);
+               importer->package->postun.body =
+                       hashtable_tokenize(&importer->table, body);
+               break;
+       default:
+               break;
+       }
+}
+
+/**
  * razor_importer_add_property:
  * @importer: the %razor_importer
  * @name: name of the property
index 44b6ce0..0935e23 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
  * Copyright (C) 2008  Red Hat, Inc
+ * Copyright (C) 2009  J. Ali Harlow <ali@juiblex.co.uk>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -18,6 +19,7 @@
  */
 
 #include <string.h>
+#include <assert.h>
 #include "razor-internal.h"
 #include "razor.h"
 
@@ -30,6 +32,7 @@ struct source {
 };
 
 struct razor_merger {
+       int committed;
        struct razor_set *set;
        struct hashtable table;
        struct hashtable file_table;
@@ -79,6 +82,8 @@ razor_merger_add_package(struct razor_merger *merger,
        struct source *source;
        uint32_t flags;
 
+       assert(merger->committed == 0);
+
        set1 = merger->source1.set;
        if (set1->packages.data <= (void *) package &&
            (void *) package < set1->packages.data + set1->packages.size) {
@@ -111,6 +116,15 @@ razor_merger_add_package(struct razor_merger *merger,
                source->file_map[r->data] = 1;
                r = list_next(r);
        }
+
+       p->preun.program = hashtable_tokenize(&merger->table,
+                                             &pool[package->preun.program]);
+       p->preun.body = hashtable_tokenize(&merger->table,
+                                          &pool[package->preun.body]);
+       p->postun.program = hashtable_tokenize(&merger->table,
+                                              &pool[package->postun.program]);
+       p->postun.body = hashtable_tokenize(&merger->table,
+                                           &pool[package->postun.body]);
 }
 
 static uint32_t
@@ -481,9 +495,8 @@ rebuild_file_package_lists(struct razor_set *set)
 }
 
 struct razor_set *
-razor_merger_finish(struct razor_merger *merger)
+razor_merger_commit(struct razor_merger *merger)
 {
-       struct razor_set *result;
        struct razor_package *p, *pend;
 
        /* As we built the package list, we filled out a bitvector of
@@ -523,10 +536,49 @@ razor_merger_finish(struct razor_merger *merger)
        rebuild_property_package_lists(merger->set);
        rebuild_file_package_lists(merger->set);
 
-       result = merger->set;
+       merger->committed = 1;
+
+       return merger->set;
+}
+
+void
+razor_merger_package_add_script(struct razor_merger *merger,
+                               struct razor_package *package,
+                               enum razor_property_flags script,
+                               const char *program, const char *body)
+{
+       uint32_t p, b;
+       char *pool;
+       struct razor_set *set = merger->set;
+       assert ((void *)package >= set->packages.data && \
+           (void *)package < set->packages.data + set->packages.size);
+
+       p = hashtable_tokenize(&merger->table, program);
+       b = hashtable_tokenize(&merger->table, body);
+
+       pool = merger->set->string_pool.data;
+
+       switch (script) {
+       case RAZOR_PROPERTY_PREUN:
+               assert(pool[package->preun.program] == '\0');
+               assert(pool[package->preun.body] == '\0');
+               package->preun.program = p;
+               package->preun.body = b;
+               break;
+       case RAZOR_PROPERTY_POSTUN:
+               assert(pool[package->postun.program] == '\0');
+               assert(pool[package->postun.body] == '\0');
+               package->postun.program = p;
+               package->postun.body = b;
+               break;
+       default:
+               break;
+       }
+}
+
+void razor_merger_destroy(struct razor_merger *merger)
+{
        hashtable_release(&merger->table);
        hashtable_release(&merger->file_table);
        free(merger);
-
-       return result;
 }
index ae202dc..0a8fc69 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
  * Copyright (C) 2008  Red Hat, Inc
+ * Copyright (C) 2009  J. Ali Harlow <ali@juiblex.co.uk>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -67,6 +68,11 @@ struct razor_set_header {
 #define RAZOR_FILE_POOL                        "file_pool"
 #define RAZOR_FILE_STRING_POOL         "file_string_pool"
 
+struct razor_script {
+       uint32_t program;
+       uint32_t body;
+};
+
 struct razor_package {
        unsigned int name  : 24;
        unsigned int flags : 8;
@@ -78,6 +84,8 @@ struct razor_package {
        uint32_t license;
        struct list_head properties;
        struct list_head files;
+       struct razor_script preun;
+       struct razor_script postun;
 };
 
 
@@ -175,17 +183,28 @@ void
 razor_merger_add_package(struct razor_merger *merger,
                         struct razor_package *package);
 struct razor_set *
-razor_merger_finish(struct razor_merger *merger);
+razor_merger_commit(struct razor_merger *merger);
+void
+razor_merger_package_add_script(struct razor_merger *merger,
+                               struct razor_package *package,
+                               enum razor_property_flags script,
+                               const char *program, const char *body);
+void
+razor_merger_destroy(struct razor_merger *merger);
 
 int run_lua_script(const char *root, const char *name, const char *body,
                   ssize_t len);
 
+int razor_run_script(const char *root, enum razor_property_flags script,
+                    const char *program, const char *body);
+
 /* Utility functions */
 
 void
 razor_package_get_details_varg(struct razor_set *set,
                               struct razor_package *package,
                               va_list args);
+void razor_rpm_get_details_varg(struct razor_rpm *rpm, va_list args);
 
 int razor_create_dir(const char *root, const char *path);
 int razor_write(int fd, const void *data, size_t size);
index aed65da..a5e1a37 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
  * Copyright (C) 2008  Red Hat, Inc
+ * Copyright (C) 2009  J. Ali Harlow <ali@juiblex.co.uk>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -34,6 +35,7 @@
 #include <errno.h>
 #include <ctype.h>
 #include <fnmatch.h>
+#include <limits.h>
 #include <assert.h>
 
 #include "razor-internal.h"
@@ -410,6 +412,22 @@ razor_package_get_details_type(struct razor_set *set,
                pool = set->details_string_pool.data;
                return &pool[package->license];
 
+       case RAZOR_DETAIL_PREUNPROG:
+               pool = set->string_pool.data;
+               return &pool[package->preun.program];
+
+       case RAZOR_DETAIL_PREUN:
+               pool = set->string_pool.data;
+               return &pool[package->preun.body];
+
+       case RAZOR_DETAIL_POSTUNPROG:
+               pool = set->string_pool.data;
+               return &pool[package->postun.program];
+
+       case RAZOR_DETAIL_POSTUN:
+               pool = set->string_pool.data;
+               return &pool[package->postun.body];
+
        default:
                fprintf(stderr, "type %u not found\n", type);
                return NULL;
@@ -466,6 +484,60 @@ razor_package_get_details(struct razor_set *set, struct razor_package *package,
        va_end (args);
 }
 
+/**
+ * razor_package_remove:
+ * @set: a %razor_set
+ * @package: a %razor_package
+ * @root: the root into which the package is currently installed
+ *
+ * Removes an installed package.
+ **/
+RAZOR_EXPORT int
+razor_package_remove(struct razor_set *set, struct razor_package *package,
+                    const char *root)
+{
+       struct razor_file_iterator *fi;
+       struct razor_package_iterator *pi;
+       struct razor_package *p;
+       char buffer[PATH_MAX];
+       const char *name, *program, *script;
+       int retval = 0, count;
+
+       razor_package_get_details(set, package,
+                                 RAZOR_DETAIL_PREUNPROG, &program,
+                                 RAZOR_DETAIL_PREUN, &script,
+                                 RAZOR_DETAIL_LAST);
+
+       if (razor_run_script(root, RAZOR_PROPERTY_PREUN, program, script))
+               return -1;
+
+       fi = razor_file_iterator_create(set, package);
+
+       while (!retval && razor_file_iterator_next(fi, &name)) {
+               pi = razor_package_iterator_create_for_file(set, name);
+               count = 0;
+               while (razor_package_iterator_next(pi, &p, RAZOR_DETAIL_LAST))
+                       count++;
+               razor_package_iterator_destroy(pi);
+               if (count <= 1) {
+                       snprintf(buffer, sizeof buffer, "%s%s", root, name);
+                       retval = remove(buffer);
+               }
+       }
+
+       razor_file_iterator_destroy(fi);
+
+       if (retval)
+               return retval;
+
+       razor_package_get_details(set, package,
+                                 RAZOR_DETAIL_POSTUNPROG, &program,
+                                 RAZOR_DETAIL_POSTUN, &script,
+                                 RAZOR_DETAIL_LAST);
+
+       return razor_run_script(root, RAZOR_PROPERTY_POSTUN, program, script);
+}
+
 RAZOR_EXPORT const char *
 razor_property_relation_to_string(struct razor_property *p)
 {
index 64b1536..a2fb076 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
  * Copyright (C) 2008  Red Hat, Inc
+ * Copyright (C) 2009  J. Ali Harlow <ali@juiblex.co.uk>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -36,7 +37,11 @@ enum razor_detail_type {
        RAZOR_DETAIL_SUMMARY,
        RAZOR_DETAIL_DESCRIPTION,
        RAZOR_DETAIL_URL,
-       RAZOR_DETAIL_LICENSE
+       RAZOR_DETAIL_LICENSE,
+       RAZOR_DETAIL_PREUNPROG,
+       RAZOR_DETAIL_PREUN,
+       RAZOR_DETAIL_POSTUNPROG,
+       RAZOR_DETAIL_POSTUN
 };
 
 enum razor_property_flags {
@@ -103,6 +108,9 @@ razor_set_get_package(struct razor_set *set, const char *package);
 void
 razor_package_get_details(struct razor_set *set,
                          struct razor_package *package, ...);
+int
+razor_package_remove(struct razor_set *set, struct razor_package *package,
+                    const char *root);
 
 
 /**
@@ -234,6 +242,8 @@ void razor_install_iterator_destroy(struct razor_install_iterator *ii);
  * from packages from one or more other package sets.
  **/
 
+struct razor_rpm;
+
 struct razor_transaction *
 razor_transaction_create(struct razor_set *system, struct razor_set *upstream);
 void razor_transaction_install_package(struct razor_transaction *transaction,
@@ -242,10 +252,13 @@ void razor_transaction_remove_package(struct razor_transaction *transaction,
                                      struct razor_package *package);
 void razor_transaction_update_package(struct razor_transaction *trans,
                                      struct razor_package *package);
+void razor_transaction_fixup_package(struct razor_transaction *trans,
+                                    struct razor_package *package,
+                                    struct razor_rpm *rpm);
 void razor_transaction_update_all(struct razor_transaction *transaction);
 int razor_transaction_resolve(struct razor_transaction *trans);
 int razor_transaction_describe(struct razor_transaction *trans);
-struct razor_set *razor_transaction_finish(struct razor_transaction *trans);
+struct razor_set *razor_transaction_commit(struct razor_transaction *trans);
 void razor_transaction_destroy(struct razor_transaction *trans);
 
 /* Temporary helper for test suite. */
@@ -264,7 +277,6 @@ int razor_transaction_unsatisfied_property(struct razor_transaction *trans,
  **/
 
 struct razor_relocations;
-struct razor_rpm;
 
 struct razor_relocations *razor_relocations_create(void);
 void razor_relocations_add(struct razor_relocations *relocations,
@@ -276,6 +288,7 @@ const char *razor_relocations_apply(struct razor_relocations *relocations,
 void razor_relocations_destroy(struct razor_relocations *relocations);
 
 struct razor_rpm *razor_rpm_open(const char *filename);
+void razor_rpm_get_details(struct razor_rpm *rpm, ...);
 void razor_rpm_set_relocations(struct razor_rpm *rpm,
                               struct razor_relocations *relocations);
 int razor_rpm_install(struct razor_rpm *rpm, const char *root);
@@ -332,6 +345,10 @@ void razor_importer_add_details(struct razor_importer *importer,
                                const char *description,
                                const char *url,
                                const char *license);
+void razor_importer_add_script(struct razor_importer *importer,
+                              enum razor_property_flags script,
+                              const char *program,
+                              const char *body);
 void razor_importer_add_property(struct razor_importer *importer,
                                 const char *name,
                                 uint32_t flags,
index c3bb5c9..a46a979 100644 (file)
@@ -256,6 +256,7 @@ struct razor_rpm {
        size_t size;
        void *payload;
        struct razor_relocations *relocations;
+       char *evr;
 };
 
 enum razor_relocation_flags {
@@ -491,6 +492,95 @@ import_files(struct razor_importer *importer, struct razor_rpm *rpm)
        }
 }
 
+static void
+razor_rpm_build_evr(struct razor_rpm *rpm)
+{
+       const char *version, *release;
+       const uint32_t *epoch;
+       char evr[128], buf[16];
+
+       epoch = razor_rpm_get_indirect(rpm, RPMTAG_EPOCH, NULL);
+       version = razor_rpm_get_indirect(rpm, RPMTAG_VERSION, NULL);
+       release = razor_rpm_get_indirect(rpm, RPMTAG_RELEASE, NULL);
+       if (epoch)
+               snprintf(buf, sizeof buf, "%lu", (unsigned long)ntohl(*epoch));
+       razor_build_evr(evr, sizeof evr, epoch ? buf : NULL, version, release);
+       rpm->evr = strdup(evr);
+}
+
+static const char *
+razor_rpm_get_details_type(struct razor_rpm *rpm, enum razor_detail_type type)
+{
+       switch(type) {
+       case RAZOR_DETAIL_NAME:
+               return razor_rpm_get_indirect(rpm, RPMTAG_NAME, NULL);
+
+       case RAZOR_DETAIL_VERSION:
+               if (!rpm->evr)
+                       razor_rpm_build_evr(rpm);
+               return rpm->evr;
+
+       case RAZOR_DETAIL_ARCH:
+               return razor_rpm_get_indirect(rpm, RPMTAG_ARCH, NULL);
+
+       case RAZOR_DETAIL_SUMMARY:
+               return razor_rpm_get_indirect(rpm, RPMTAG_SUMMARY, NULL);
+
+       case RAZOR_DETAIL_DESCRIPTION:
+               return razor_rpm_get_indirect(rpm, RPMTAG_DESCRIPTION, NULL);
+
+       case RAZOR_DETAIL_URL:
+               return razor_rpm_get_indirect(rpm, RPMTAG_URL, NULL);
+
+       case RAZOR_DETAIL_LICENSE:
+               return razor_rpm_get_indirect(rpm, RPMTAG_LICENSE, NULL);
+
+       case RAZOR_DETAIL_PREUNPROG:
+               return razor_rpm_get_indirect(rpm, RPMTAG_PREUNPROG, NULL);
+
+       case RAZOR_DETAIL_PREUN:
+               return razor_rpm_get_indirect(rpm, RPMTAG_PREUN, NULL);
+
+       case RAZOR_DETAIL_POSTUNPROG:
+               return razor_rpm_get_indirect(rpm, RPMTAG_POSTUNPROG, NULL);
+
+       case RAZOR_DETAIL_POSTUN:
+               return razor_rpm_get_indirect(rpm, RPMTAG_POSTUN, NULL);
+
+       default:
+               fprintf(stderr, "type %u not found\n", type);
+               return NULL;
+       }
+}
+
+void
+razor_rpm_get_details_varg(struct razor_rpm *rpm, va_list args)
+{
+       int i;
+       enum razor_detail_type type;
+       const char **data;
+
+       for (i = 0;; i += 2) {
+               type = va_arg(args, enum razor_detail_type);
+               if (type == RAZOR_DETAIL_LAST)
+                       break;
+               data = va_arg(args, const char **);
+                *data = razor_rpm_get_details_type(rpm, type);
+        }
+}
+
+RAZOR_EXPORT void
+razor_rpm_get_details(struct razor_rpm *rpm, ...)
+{
+       va_list args;
+
+       assert(rpm != NULL);
+
+       va_start(args, rpm);
+       razor_rpm_get_details_varg(rpm, args);
+       va_end(args);
+}
+
 RAZOR_EXPORT struct razor_rpm *
 razor_rpm_open(const char *filename)
 {
@@ -865,7 +955,7 @@ run_script(struct installer *installer,
                }
        }
 
-       if (strcmp(program, "<lua>") == 0)
+       if (program && strcmp(program, "<lua>") == 0)
                retval = run_script_lua(installer->root, script_tag, script);
        else
                retval = run_script_external(installer->root, program, script);
@@ -881,6 +971,47 @@ run_script(struct installer *installer,
        return retval;
 }
 
+int
+razor_run_script(const char *root, enum razor_property_flags script,
+                const char *program, const char *body)
+{
+       int retval;
+       unsigned int script_tag;
+
+       if (program && !*program)
+               program = NULL;
+       if (body && !*body)
+               body = NULL;
+       if (program == NULL && body == NULL)
+               return 0;
+
+       if (program && strcmp(program, "<lua>") == 0)
+       {
+               switch(script) {
+               case RAZOR_PROPERTY_PRE:
+                       script_tag = RPMTAG_PREIN;
+                       break;
+               case RAZOR_PROPERTY_POST:
+                       script_tag = RPMTAG_POSTIN;
+                       break;
+               case RAZOR_PROPERTY_PREUN:
+                       script_tag = RPMTAG_PREUN;
+                       break;
+               case RAZOR_PROPERTY_POSTUN:
+                       script_tag = RPMTAG_POSTUN;
+                       break;
+               default:
+                       script_tag = 0;
+                       break;
+               }
+               retval = run_script_lua(root, script_tag, body);
+       }
+       else
+               retval = run_script_external(root, program, body);
+
+       return retval;
+}
+
 static int
 installer_init(struct installer *installer)
 {
@@ -1035,6 +1166,7 @@ razor_rpm_close(struct razor_rpm *rpm)
        free(rpm->dirs);
        free(rpm->prefixes);
        err = razor_file_free_contents(rpm->map, rpm->size);
+       free(rpm->evr);
        free(rpm);
 
        return err;
@@ -1043,32 +1175,23 @@ razor_rpm_close(struct razor_rpm *rpm)
 RAZOR_EXPORT int
 razor_importer_add_rpm(struct razor_importer *importer, struct razor_rpm *rpm)
 {
-       const char *name, *version, *release, *arch;
+       const char *name, *version, *arch;
        const char *summary, *description, *url, *license;
-       const uint32_t *epoch;
-       char evr[128], buf[16];
 
        assert (importer != NULL);
        assert (rpm != NULL);
 
-       name = razor_rpm_get_indirect(rpm, RPMTAG_NAME, NULL);
-       epoch = razor_rpm_get_indirect(rpm, RPMTAG_EPOCH, NULL);
-       version = razor_rpm_get_indirect(rpm, RPMTAG_VERSION, NULL);
-       release = razor_rpm_get_indirect(rpm, RPMTAG_RELEASE, NULL);
-       arch = razor_rpm_get_indirect(rpm, RPMTAG_ARCH, NULL);
-
-       summary = razor_rpm_get_indirect(rpm, RPMTAG_SUMMARY, NULL);
-       description = razor_rpm_get_indirect(rpm, RPMTAG_DESCRIPTION, NULL);
-       url = razor_rpm_get_indirect(rpm, RPMTAG_URL, NULL);
-       license = razor_rpm_get_indirect(rpm, RPMTAG_LICENSE, NULL);
-
-       if (epoch) {
-               snprintf(buf, sizeof buf, "%lu", ntohl(*epoch));
-               razor_build_evr(evr, sizeof evr, buf, version, release);
-       } else {
-               razor_build_evr(evr, sizeof evr, NULL, version, release);
-       }
-       razor_importer_begin_package(importer, name, evr, arch);
+       razor_rpm_get_details(rpm,
+                             RAZOR_DETAIL_NAME, &name,
+                             RAZOR_DETAIL_VERSION, &version,
+                             RAZOR_DETAIL_ARCH, &arch,
+                             RAZOR_DETAIL_SUMMARY, &summary,
+                             RAZOR_DETAIL_DESCRIPTION, &description,
+                             RAZOR_DETAIL_URL, &url,
+                             RAZOR_DETAIL_LICENSE, &license,
+                             RAZOR_DETAIL_LAST);
+
+       razor_importer_begin_package(importer, name, version, arch);
 
        razor_importer_add_details(importer, summary, description, url,
                                   license);
index e6e9bfb..50d13d6 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
  * Copyright (C) 2008  Red Hat, Inc
+ * Copyright (C) 2009  J. Ali Harlow <ali@juiblex.co.uk>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -100,6 +101,7 @@ struct razor_transaction {
        int package_count, errors;
        struct transaction_set system, upstream;
        int changes;
+       struct razor_merger *merger;
 };
 
 static void
@@ -854,9 +856,8 @@ razor_transaction_unsatisfied_property(struct razor_transaction *trans,
 }
 
 RAZOR_EXPORT struct razor_set *
-razor_transaction_finish(struct razor_transaction *trans)
+razor_transaction_commit(struct razor_transaction *trans)
 {
-       struct razor_merger *merger;
        struct razor_package *u, *uend, *upkgs, *s, *send, *spkgs;
        char *upool, *spool;
        int cmp;
@@ -873,7 +874,8 @@ razor_transaction_finish(struct razor_transaction *trans)
                trans->upstream.set->packages.size;
        upool = trans->upstream.set->string_pool.data;
 
-       merger = razor_merger_create(trans->system.set, trans->upstream.set);
+       trans->merger = razor_merger_create(trans->system.set,
+                                           trans->upstream.set);
        while (s < send || u < uend) {
                if (s < send && u < uend)
                        cmp = strcmp(&spool[s->name], &upool[u->name]);
@@ -884,26 +886,46 @@ razor_transaction_finish(struct razor_transaction *trans)
 
                if (cmp < 0) {
                        if (trans->system.packages[s - spkgs] & TRANS_PACKAGE_PRESENT)
-                               razor_merger_add_package(merger, s);
+                               razor_merger_add_package(trans->merger, s);
                        s++;
                } else if (cmp == 0) {
                        if (trans->system.packages[s - spkgs] & TRANS_PACKAGE_PRESENT)
-                               razor_merger_add_package(merger, s);
+                               razor_merger_add_package(trans->merger, s);
                        if (trans->upstream.packages[u - upkgs] & TRANS_PACKAGE_PRESENT)
-                               razor_merger_add_package(merger, u);
+                               razor_merger_add_package(trans->merger, u);
 
                        s++;
                        u++;
                } else {
                        if (trans->upstream.packages[u - upkgs] & TRANS_PACKAGE_PRESENT)
-                               razor_merger_add_package(merger, u);
+                               razor_merger_add_package(trans->merger, u);
                        u++;
                }
        }
 
-       razor_transaction_destroy(trans);
+       return razor_merger_commit(trans->merger);
+}
+
+RAZOR_EXPORT void
+razor_transaction_fixup_package(struct razor_transaction *trans,
+                               struct razor_package *package,
+                               struct razor_rpm *rpm)
+{
+       const char *preunprog, *preun, *postunprog, *postun;
+
+       razor_rpm_get_details(rpm,
+                             RAZOR_DETAIL_PREUNPROG, &preunprog,
+                             RAZOR_DETAIL_PREUN, &preun,
+                             RAZOR_DETAIL_POSTUNPROG, &postunprog,
+                             RAZOR_DETAIL_POSTUN, &postun,
+                             RAZOR_DETAIL_LAST);
 
-       return razor_merger_finish(merger);
+       razor_merger_package_add_script(trans->merger, package,
+                                       RAZOR_PROPERTY_PREUN,
+                                       preunprog, preun);
+       razor_merger_package_add_script(trans->merger, package,
+                                       RAZOR_PROPERTY_POSTUN,
+                                       postunprog, postun);
 }
 
 RAZOR_EXPORT void
@@ -911,6 +933,8 @@ razor_transaction_destroy(struct razor_transaction *trans)
 {
        assert (trans != NULL);
 
+       if (trans->merger)
+               razor_merger_destroy(trans->merger);
        transaction_set_release(&trans->system);
        transaction_set_release(&trans->upstream);
        free(trans);
index bb69c7b..8ec7cbe 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
  * Copyright (C) 2008  Red Hat, Inc
+ * Copyright (C) 2009  J. Ali Harlow <ali@juiblex.co.uk>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -79,6 +80,21 @@ add_properties(struct razor_importer *importer,
                                            versions.list[i]);
 }
 
+static void
+add_script(struct razor_importer *importer,
+          uint32_t type_flags, Header h,
+          int32_t program_tag, int32_t body_tag)
+{
+       union rpm_entry program, body;
+       int32_t type, count;
+
+       headerGetEntry(h, program_tag, &type, &program.p, &count);
+       headerGetEntry(h, body_tag, &type, &body.p, &count);
+
+       razor_importer_add_script(importer, type_flags,
+                                 program.string, body.string);
+}
+
 struct razor_set *
 razor_set_create_from_rpmdb(void)
 {
@@ -163,6 +179,12 @@ razor_set_create_from_rpmdb(void)
                        razor_importer_add_file(importer, filename);
                }
 
+               add_script(importer, RAZOR_PROPERTY_PREUN, h,
+                          RPMTAG_PREUNPROG, RPMTAG_PREUN);
+
+               add_script(importer, RAZOR_PROPERTY_POSTUN, h,
+                          RPMTAG_POSTUNPROG, RPMTAG_POSTUN);
+
                razor_importer_finish_package(importer);
 
                printf("\rimporting %d", ++imported_count);
index db055be..74908e6 100644 (file)
@@ -50,8 +50,8 @@ static const char *yum_url;
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
 
 static int
-update_packages(struct razor_set *system, struct razor_set *next,
-               struct razor_relocations *relocations);
+update_packages(struct razor_transaction *trans, struct razor_set *system,
+               struct razor_set *next, struct razor_relocations *relocations);
 
 static struct razor_package_iterator *
 create_iterator_from_argv(struct razor_set *set, int argc, const char *argv[])
@@ -222,6 +222,44 @@ command_list_conflicts(int argc, const char *argv[])
 }
 
 static int
+command_list_scripts(int argc, const char *argv[])
+{
+       struct razor_set *set;
+       struct razor_package *package;
+       struct razor_package_iterator *pi;
+       const char *preunprog, *preun, *postunprog, *postun;
+
+       set = razor_root_open_read_only(install_root);
+       if (set == NULL)
+               return 1;
+
+       pi = create_iterator_from_argv(set, argc, argv);
+       while (razor_package_iterator_next(pi, &package,
+                                          RAZOR_DETAIL_PREUNPROG, &preunprog,
+                                          RAZOR_DETAIL_PREUN, &preun,
+                                          RAZOR_DETAIL_POSTUNPROG, &postunprog,
+                                          RAZOR_DETAIL_POSTUN, &postun,
+                                          RAZOR_DETAIL_LAST)) {
+               if (preun && *preun) {
+                       printf("preuninstall scriptlet");
+                       if (preunprog && *preunprog)
+                               printf(" (using %s)",preunprog);
+                       printf(":\n%s\n",preun);
+               }
+               if (postun && *postun) {
+                       printf("postuninstall scriptlet");
+                       if (postunprog && *postunprog)
+                               printf(" (using %s)",postunprog);
+                       printf(":\n%s\n",postun);
+               }
+       }
+       razor_package_iterator_destroy(pi);
+       razor_set_destroy(set);
+
+       return 0;
+}
+
+static int
 command_list_files(int argc, const char *argv[])
 {
        struct razor_set *set;
@@ -542,6 +580,7 @@ command_update(int argc, const char *argv[])
        for (i = 0; i < argc; i++) {
                if (mark_packages_for_update(trans, set, argv[i]) == 0) {
                        fprintf(stderr, "no match for %s\n", argv[i]);
+                       razor_transaction_destroy(trans);
                        return 1;
                }
        }
@@ -550,11 +589,13 @@ command_update(int argc, const char *argv[])
        errors = razor_transaction_describe(trans);
        if (errors) {
                fprintf(stderr, "unresolved dependencies\n");
+               razor_transaction_destroy(trans);
                return 1;
        }
 
-       set = razor_transaction_finish(trans);
+       set = razor_transaction_commit(trans);
        razor_set_write(set, updated_repo_filename, RAZOR_REPO_FILE_MAIN);
+       razor_transaction_destroy(trans);
        razor_set_destroy(set);
        razor_set_destroy(upstream);
        printf("wrote system-updated.rzdb\n");
@@ -598,10 +639,11 @@ command_remove(int argc, const char *argv[])
                return 1;
        }
 
-       next = razor_transaction_finish(trans);
-       update_packages(system, next, NULL);
+       next = razor_transaction_commit(trans);
+       update_packages(trans, system, next, NULL);
        razor_root_update(root, next);
 
+       razor_transaction_destroy(trans);
        razor_set_destroy(next);
        razor_set_destroy(upstream);
 
@@ -774,6 +816,7 @@ relocate_packages(struct razor_set *set, struct razor_relocations *relocations)
        struct razor_property *property;
        struct razor_rpm *rpm;
        const char *name, *version, *arch, *summary, *desc, *url, *license;
+       const char *preunprog, *preun, *postunprog, *postun;
        char file[PATH_MAX];
        uint32_t flags;
 
@@ -788,6 +831,10 @@ relocate_packages(struct razor_set *set, struct razor_relocations *relocations)
                                           RAZOR_DETAIL_DESCRIPTION, &desc,
                                           RAZOR_DETAIL_URL, &url,
                                           RAZOR_DETAIL_LICENSE, &license,
+                                          RAZOR_DETAIL_PREUNPROG, &preunprog,
+                                          RAZOR_DETAIL_PREUN, &preun,
+                                          RAZOR_DETAIL_POSTUNPROG, &postunprog,
+                                          RAZOR_DETAIL_POSTUN, &postun,
                                           RAZOR_DETAIL_LAST)) {
                snprintf(file, sizeof file,
                         "rpms/%s", rpm_filename(name, version, arch));
@@ -820,6 +867,11 @@ relocate_packages(struct razor_set *set, struct razor_relocations *relocations)
                }
                razor_file_iterator_destroy(file_iter);
 
+               razor_importer_add_script(importer, RAZOR_PROPERTY_PREUN,
+                                         preunprog, preun);
+               razor_importer_add_script(importer, RAZOR_PROPERTY_POSTUN,
+                                         postunprog, postun);
+
                razor_importer_finish_package(importer);
        }
 
@@ -828,7 +880,8 @@ relocate_packages(struct razor_set *set, struct razor_relocations *relocations)
 }
 
 static int
-install_package(struct razor_set *set, struct razor_package *package,
+install_package(struct razor_transaction *trans, struct razor_set *set,
+               struct razor_package *package,
                struct razor_relocations *relocations)
 {
        int retval;
@@ -853,6 +906,7 @@ install_package(struct razor_set *set, struct razor_package *package,
        }
        if (relocations)
                razor_rpm_set_relocations(rpm, relocations);
+       razor_transaction_fixup_package(trans, package, rpm);
        retval = razor_rpm_install(rpm, install_root);
        if (retval < 0)
                fprintf(stderr, "failed to install rpm %s\n", file);
@@ -861,37 +915,8 @@ install_package(struct razor_set *set, struct razor_package *package,
 }
 
 static int
-remove_package(struct razor_set *set, struct razor_package *package)
-{
-       struct razor_file_iterator *fi;
-       struct razor_package_iterator *pi;
-       struct razor_package *p;
-       char buffer[PATH_MAX];
-       const char *name;
-       int retval = 0, count;
-
-       fi = razor_file_iterator_create(set, package);
-
-       while (!retval && razor_file_iterator_next(fi, &name)) {
-               pi = razor_package_iterator_create_for_file(set, name);
-               count = 0;
-               while (razor_package_iterator_next(pi, &p, RAZOR_DETAIL_LAST))
-                       count++;
-               razor_package_iterator_destroy(pi);
-               if (count <= 1) {
-                       snprintf(buffer, sizeof buffer, "%s%s", install_root,
-                                name);
-                       retval = remove(buffer);
-               }
-       }
-
-       razor_file_iterator_destroy(fi);
-       return retval;
-}
-
-static int
-update_packages(struct razor_set *system, struct razor_set *next,
-               struct razor_relocations *relocations)
+update_packages(struct razor_transaction *trans, struct razor_set *system,
+               struct razor_set *next, struct razor_relocations *relocations)
 {
        struct razor_install_iterator *ii;
        struct razor_package *package;
@@ -903,9 +928,11 @@ update_packages(struct razor_set *system, struct razor_set *next,
        while (!retval && razor_install_iterator_next(ii, &set, &package,
                                                      &action, &count)) {
                if (action == RAZOR_INSTALL_ACTION_ADD)
-                       retval = install_package(set, package, relocations);
+                       retval = install_package(trans, set, package,
+                                                relocations);
                else if (action == RAZOR_INSTALL_ACTION_REMOVE)
-                       retval = remove_package(set, package);
+                       retval = razor_package_remove(set, package,
+                                                     install_root);
        }
        razor_install_iterator_destroy(ii);
 
@@ -974,6 +1001,7 @@ command_install(int argc, const char *argv[])
        for (; i < argc; i++) {
                if (mark_packages_for_update(trans, upstream, argv[i]) == 0) {
                        fprintf(stderr, "no package matched %s\n", argv[i]);
+                       razor_transaction_destroy(trans);
                        razor_root_close(root);
                        return 1;
                }
@@ -982,28 +1010,32 @@ command_install(int argc, const char *argv[])
        if (dependencies) {
                razor_transaction_resolve(trans);
                if (razor_transaction_describe(trans) > 0) {
+                       razor_transaction_destroy(trans);
                        razor_root_close(root);
                        return 1;
                }
        }
 
-       next = razor_transaction_finish(trans);
-
-       razor_root_update(root, next);
+       next = razor_transaction_commit(trans);
 
        if (mkdir("rpms", 0777) && errno != EEXIST) {
                fprintf(stderr, "failed to create rpms directory.\n");
+               razor_transaction_destroy(trans);
                razor_root_close(root);
                return 1;
        }
 
        if (download_packages(system, next) < 0) {
+               razor_transaction_destroy(trans);
                razor_root_close(root);
                 return 1;
         }
 
-       update_packages(system, next, relocations);
+       update_packages(trans, system, next, relocations);
+
+       razor_root_update(root, next);
 
+       razor_transaction_destroy(trans);
        if (relocations)
                razor_relocations_destroy(relocations);
        razor_set_destroy(next);
@@ -1167,6 +1199,7 @@ static struct {
        { "list-provides", "list all provides for the given package", command_list_provides },
        { "list-obsoletes", "list all obsoletes for the given package", command_list_obsoletes },
        { "list-conflicts", "list all conflicts for the given package", command_list_conflicts },
+       { "list-scripts", "list all scripts for the given package", command_list_scripts },
        { "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 },
index 4c288b4..225bb99 100644 (file)
--- a/src/rpm.c
+++ b/src/rpm.c
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
  * Copyright (C) 2008  Red Hat, Inc
+ * Copyright (C) 2009  J. Ali Harlow <ali@juiblex.co.uk>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -602,17 +603,21 @@ command_erase(int argc, const char *argv[])
 
        if (!option_nodeps && razor_transaction_describe(trans) > 0) {
                printf("unsatisfied dependencies.\n");
+               razor_transaction_destroy(trans);
                exit(1);
        }
 
-       if (option_test)
+       if (option_test) {
+               razor_transaction_destroy(trans);
                exit(0);
+       }
 
-       next = razor_transaction_finish(trans);
+       next = razor_transaction_commit(trans);
 
        if (!option_justdb)
                razor_set_diff(set, next, update_package, NULL);
 
+       razor_transaction_destroy(trans);
        razor_set_destroy(set);
        razor_set_destroy(upstream);
 
@@ -644,17 +649,21 @@ command_install(int argc, const char *argv[])
 
        if (!option_nodeps && razor_transaction_describe(trans) > 0) {
                printf("unsatisfied dependencies.\n");
+               razor_transaction_destroy(trans);
                exit(1);
        }
 
-       if (option_test)
+       if (option_test) {
+               razor_transaction_destroy(trans);
                exit(0);
+       }
 
-       next = razor_transaction_finish(trans);
+       next = razor_transaction_commit(trans);
 
        if (!option_justdb)
                razor_set_diff(set, next, update_package, NULL);
 
+       razor_transaction_destroy(trans);
        razor_set_destroy(set);
        razor_set_destroy(upstream);
 
@@ -686,17 +695,21 @@ command_update(int argc, const char *argv[])
 
        if (!option_nodeps && razor_transaction_describe(trans) > 0) {
                printf("unsatisfied dependencies.\n");
+               razor_transaction_destroy(trans);
                exit(1);
        }
 
-       if (option_test)
+       if (option_test) {
+               razor_transaction_destroy(trans);
                exit(0);
+       }
 
-       next = razor_transaction_finish(trans);
+       next = razor_transaction_commit(trans);
 
        if (!option_justdb)
                razor_set_diff(set, next, update_package, NULL);
 
+       razor_transaction_destroy(trans);
        razor_set_destroy(set);
        razor_set_destroy(upstream);
 
index f55049d..160a3ad 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
  * Copyright (C) 2008  Red Hat, Inc
+ * Copyright (C) 2009  J. Ali Harlow <ali@juiblex.co.uk>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -336,7 +337,8 @@ end_transaction(struct test_context *ctx)
 
        if (!errors) {
                struct razor_set *new;
-               new = razor_transaction_finish(ctx->trans);
+               new = razor_transaction_commit(ctx->trans);
+               razor_transaction_destroy(ctx->trans);
                ctx->trans = NULL;
                ctx->system_set = new;
        }
index e08fbb6..5298e6b 100755 (executable)
@@ -1,4 +1,19 @@
 #!/bin/sh
+fs_check_file()
+{
+    if [ ! -e "$RAZOR_ROOT$1" ]; then 
+       echo $1: Not in filesystem >&2
+       ls -R "$RAZOR_ROOT" >&2
+       exit 1
+    fi
+}
+fs_check_no_file()
+{
+    if [ -e "$RAZOR_ROOT$1" ]; then 
+       echo $1: Still in filesystem >&2
+       exit 1
+    fi
+}
 check_file()
 {
     ../src/razor list-files | grep -x "$1" > /dev/null
@@ -28,10 +43,7 @@ check_file()
            exit 1
        fi
     done
-    if [ ! -e "$RAZOR_ROOT$1" ]; then 
-       echo $1: Not in filesystem >&2
-       exit 1
-    fi
+    fs_check_file $1
 }
 check_no_file()
 {
@@ -40,19 +52,18 @@ check_no_file()
        echo $1: Still in database >&2
        exit 1
     fi
-    if [ -e "$RAZOR_ROOT$1" ]; then 
-       echo $1: Still in filesystem >&2
-       exit 1
-    fi
+    fs_check_no_file $1
 }
 export RAZOR_ROOT=`mktemp -dt` || exit 1
 ../src/razor init || exit 1
 export YUM_URL="file://localhost/`pwd`"
 ../src/razor import-yum || exit 1
 ../src/razor install zip || exit 1
+fs_check_file /usr/var/lib/zip/data.zap
 ../src/razor remove zip || exit 1
 check_file /usr/bin/zap
 check_no_file /usr/bin/zip
+fs_check_no_file /usr/var/lib/zip/data.zap
 ../src/razor install zsh || exit 1
 ../src/razor install zsh2 || exit 1
 ../src/razor remove zsh || exit 1
index c433a8e..ed7a619 100644 (file)
@@ -43,7 +43,6 @@ if posix.stat(prefix.."/bin/zap")~=nil then
 end
 
 %postun -p <lua>
-print("zip: postun script\n");
 prefix=posix.getenv("RPM_INSTALL_PREFIX0")
 if prefix==nil then
     prefix="/usr"