Order the installation and removal of packages correctly so scripts can run
authorJ. Ali Harlow <ali@juiblex.co.uk>
Thu, 14 May 2009 04:55:19 +0000 (05:55 +0100)
committerJ. Ali Harlow <ali@juiblex.co.uk>
Thu, 14 May 2009 04:55:19 +0000 (05:55 +0100)
librazor/razor.c
test/Makefile.am
test/order.sh [new file with mode: 0755]
test/zip.spec
test/zsh.spec

index 8795684..aed65da 100644 (file)
@@ -624,11 +624,6 @@ razor_set_list_package_files(struct razor_set *set,
        razor_file_iterator_destroy(fi);
 }
 
-/* The diff order matters.  We should sort the packages so that a
- * REMOVE of a package comes before the INSTALL, and so that all
- * requires for a package have been installed before the package.
- **/
-
 RAZOR_EXPORT void
 razor_set_diff(struct razor_set *set, struct razor_set *upstream,
               razor_diff_callback_t callback, void *data)
@@ -698,7 +693,7 @@ struct razor_install_iterator {
        struct razor_set *set;
        struct razor_set *next;
        struct array actions;
-       struct install_action *a, *end;
+       struct deque *order;
 };
 
 static void
@@ -730,6 +725,15 @@ razor_set_create_install_iterator(struct razor_set *set,
                                  struct razor_set *next)
 {
        struct razor_install_iterator *ii;
+       struct razor_property *prop;
+       /* A graph of the actions to be perfomed where
+        * A->B means action A should follow action B.
+        */
+       struct graph follows;
+       struct install_action *actions, *ai, *aj;
+       int i, j, count, vertex_added;
+       struct list *link;
+       struct razor_set *rs;
 
        assert (set != NULL);
        assert (next != NULL);
@@ -740,11 +744,58 @@ razor_set_create_install_iterator(struct razor_set *set,
        
        razor_set_diff(set, next, add_action, ii);
 
-       ii->a = ii->actions.data;
-       ii->end = ii->actions.data + ii->actions.size;
+       actions = ii->actions.data;
+       count = ii->actions.size / sizeof (struct install_action);
+
+       graph_init(&follows);
+
+       for(i = 0; i < count; i++) {
+               ai = actions + i;
+               rs = ai->action == RAZOR_INSTALL_ACTION_ADD ? next : set;
+               vertex_added = 0;
+               link = list_first(&ai->package->properties, &rs->property_pool);
+               for(; link; link = list_next(link)) {
+                       prop = rs->properties.data;
+                       prop += link->data;
+                       switch(prop->flags & RAZOR_PROPERTY_TYPE_MASK) {
+                       case RAZOR_PROPERTY_REQUIRES:
+                       case RAZOR_PROPERTY_CONFLICTS:
+                               for(j = 0; j < count; j++) {
+                                       if (j == i)
+                                               continue;
+                                       aj = actions + j;
+                                       if (aj->package->name == prop->name) {
+                                               if (ai->action ==
+                                                   RAZOR_INSTALL_ACTION_ADD)
+                                                       graph_add_edge(&follows,
+                                                                      i, j);
+                                               else
+                                                       graph_add_edge(&follows,
+                                                                      j, i);
+                                               vertex_added++;
+                                       }
+                               }
+                               break;
+                       }
+               }
+               if (ai->action == RAZOR_INSTALL_ACTION_ADD) {
+                       for(j = 0; j < count; j++) {
+                               if (j == i)
+                                       continue;
+                               aj = actions + j;
+                               if (aj->package == ai->package &&
+                                   aj->action == RAZOR_INSTALL_ACTION_REMOVE) {
+                                       graph_add_edge(&follows, i, j);
+                                       vertex_added++;
+                               }
+                       }
+               }
+               if (!vertex_added)
+                       graph_add_edge(&follows, i, i);
+       }
 
-       /* FIXME: We need to figure out the right install order here,
-        * so the post and pre scripts can run. */
+       ii->order = graph_sort(&follows);
+       graph_release(&follows);
 
        return ii;
 }
@@ -756,10 +807,12 @@ razor_install_iterator_next(struct razor_install_iterator *ii,
                            enum razor_install_action *action,
                            int *count)
 {
-       if (ii->a == ii->end)
+       struct install_action *a;
+       if (deque_empty(ii->order))
                return 0;
 
-       switch (ii->a->action) {
+       a = (struct install_action *)ii->actions.data + deque_pop(ii->order);
+       switch (a->action) {
        case RAZOR_INSTALL_ACTION_ADD:
                *set = ii->next;
                break;
@@ -768,10 +821,9 @@ razor_install_iterator_next(struct razor_install_iterator *ii,
                break;
        }
 
-       *package = ii->a->package;
-       *action = ii->a->action;
+       *package = a->package;
+       *action = a->action;
        *count = 0;
-       ii->a++;
 
        return 1;
 }
@@ -780,5 +832,6 @@ RAZOR_EXPORT void
 razor_install_iterator_destroy(struct razor_install_iterator *ii)
 {
        array_release(&ii->actions);
+       deque_free(ii->order);
        free(ii);
 }
index f567b95..7109c10 100644 (file)
@@ -4,6 +4,7 @@ check_SCRIPTS = relocate named-root remove
 if HAVE_LUA
   check_SCRIPTS += lua
 endif
+check_SCRIPTS += order
 
 relocate:      relocate.sh primary.xml.gz
        cp $(srcdir)/relocate.sh relocate
@@ -14,6 +15,9 @@ named-root:   named-root.sh primary.xml.gz
 remove:        remove.sh primary.xml.gz
        cp $(srcdir)/remove.sh remove
 
+order: order.sh primary.xml.gz
+       cp $(srcdir)/order.sh order
+
 lua:   lua.sh primary.xml.gz
        cp $(srcdir)/lua.sh lua
 
@@ -39,6 +43,7 @@ EXTRA_DIST =                  \
        zsh.spec                \
        zsh2.spec               \
        filesystem.spec         \
+       order.sh                \
        lua.sh                  \
        remove.sh               \
        named-root.sh           \
diff --git a/test/order.sh b/test/order.sh
new file mode 100755 (executable)
index 0000000..07441fa
--- /dev/null
@@ -0,0 +1,16 @@
+#!/bin/sh
+check_file()
+{
+    if [ ! -e "$RAZOR_ROOT$1" ]; then 
+       echo $1: Not in filesystem >&2
+       exit 1
+    fi
+}
+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 zsh || exit 1
+check_file /usr/var/lib/zip/data.zap
+check_file /usr/var/lib/zsh/data.zip
+rm -rf "$RAZOR_ROOT"
index 8559975..c433a8e 100644 (file)
@@ -23,5 +23,35 @@ touch $RPM_BUILD_ROOT/usr/bin/zip
 
 %clean
 
+%pre -p <lua>
+function mkdir_missing(dir)
+    if posix.stat(dir)==nil then
+       posix.mkdir(dir)
+    end
+end
+prefix=posix.getenv("RPM_INSTALL_PREFIX0")
+if prefix==nil then
+    prefix="/usr"
+end
+if posix.stat(prefix.."/bin/zap")~=nil then
+    mkdir_missing(prefix.."/var")
+    mkdir_missing(prefix.."/var/lib")
+    posix.mkdir(prefix.."/var/lib/zip")
+    io.output(prefix.."/var/lib/zip/data.zap")
+    io.write("Important data\n");
+    io.close()
+end
+
+%postun -p <lua>
+print("zip: postun script\n");
+prefix=posix.getenv("RPM_INSTALL_PREFIX0")
+if prefix==nil then
+    prefix="/usr"
+end
+if posix.stat(prefix.."/bin/zap")~=nil then
+    os.remove(prefix.."/var/lib/zip/data.zap")
+    os.remove(prefix.."/var/lib/zip")
+end
+
 %files
 /usr/bin/zip
index 72e0dda..5523a0f 100644 (file)
@@ -25,6 +25,35 @@ echo "DEVICE /dev/tty" > $RPM_BUILD_ROOT/etc/zsh.conf
 
 %clean
 
+%pre -p <lua>
+function mkdir_missing(dir)
+    if posix.stat(dir)==nil then
+       posix.mkdir(dir)
+    end
+end
+prefix=posix.getenv("RPM_INSTALL_PREFIX0")
+if prefix==nil then
+    prefix="/usr"
+end
+if posix.stat(prefix.."/bin/zip")~=nil then
+    mkdir_missing(prefix.."/var")
+    mkdir_missing(prefix.."/var/lib")
+    posix.mkdir(prefix.."/var/lib/zsh")
+    io.output(prefix.."/var/lib/zsh/data.zip")
+    io.write("Important data\n");
+    io.close()
+end
+
+%postun -p <lua>
+prefix=posix.getenv("RPM_INSTALL_PREFIX0")
+if prefix==nil then
+    prefix="/usr"
+end
+if posix.stat(prefix.."/bin/zip")~=nil then
+    os.remove(prefix.."/var/lib/zsh/data.zip")
+    os.remove(prefix.."/var/lib/zsh")
+end
+
 %files
 /usr/bin/zsh
 /etc/zsh.conf