# HG changeset patch # User J. Ali Harlow # Date 1242276919 -3600 # Node ID e45f50e940b63a90984d0bb6a51262cbb60e695a # Parent f176b2ba3cb3ab6c1351590512ef5a62862b3e7b Order the installation and removal of packages correctly so scripts can run diff -r f176b2ba3cb3 -r e45f50e940b6 librazor/razor.c --- a/librazor/razor.c Thu May 14 05:51:05 2009 +0100 +++ b/librazor/razor.c Thu May 14 05:55:19 2009 +0100 @@ -624,11 +624,6 @@ 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_set *set; struct razor_set *next; struct array actions; - struct install_action *a, *end; + struct deque *order; }; static void @@ -730,6 +725,15 @@ 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_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); - /* FIXME: We need to figure out the right install order here, - * so the post and pre scripts can run. */ + 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); + } + + ii->order = graph_sort(&follows); + graph_release(&follows); return ii; } @@ -756,10 +807,12 @@ 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 @@ 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_install_iterator_destroy(struct razor_install_iterator *ii) { array_release(&ii->actions); + deque_free(ii->order); free(ii); } diff -r f176b2ba3cb3 -r e45f50e940b6 test/Makefile.am --- a/test/Makefile.am Thu May 14 05:51:05 2009 +0100 +++ b/test/Makefile.am Thu May 14 05:55:19 2009 +0100 @@ -4,6 +4,7 @@ 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 @@ 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 @@ zsh.spec \ zsh2.spec \ filesystem.spec \ + order.sh \ lua.sh \ remove.sh \ named-root.sh \ diff -r f176b2ba3cb3 -r e45f50e940b6 test/order.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/order.sh Thu May 14 05:55:19 2009 +0100 @@ -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" diff -r f176b2ba3cb3 -r e45f50e940b6 test/zip.spec --- a/test/zip.spec Thu May 14 05:51:05 2009 +0100 +++ b/test/zip.spec Thu May 14 05:55:19 2009 +0100 @@ -23,5 +23,35 @@ %clean +%pre -p +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 +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 diff -r f176b2ba3cb3 -r e45f50e940b6 test/zsh.spec --- a/test/zsh.spec Thu May 14 05:51:05 2009 +0100 +++ b/test/zsh.spec Thu May 14 05:55:19 2009 +0100 @@ -25,6 +25,35 @@ %clean +%pre -p +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 +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