Order the installation and removal of packages correctly so scripts can run
authorJ. Ali Harlow <ali@juiblex.co.uk>
Thu May 14 05:55:19 2009 +0100 (2009-05-14)
changeset 367e45f50e940b6
parent 366 f176b2ba3cb3
child 368 ea743486ba6f
Order the installation and removal of packages correctly so scripts can run
librazor/razor.c
test/Makefile.am
test/order.sh
test/zip.spec
test/zsh.spec
     1.1 --- a/librazor/razor.c	Thu May 14 05:51:05 2009 +0100
     1.2 +++ b/librazor/razor.c	Thu May 14 05:55:19 2009 +0100
     1.3 @@ -624,11 +624,6 @@
     1.4  	razor_file_iterator_destroy(fi);
     1.5  }
     1.6  
     1.7 -/* The diff order matters.  We should sort the packages so that a
     1.8 - * REMOVE of a package comes before the INSTALL, and so that all
     1.9 - * requires for a package have been installed before the package.
    1.10 - **/
    1.11 -
    1.12  RAZOR_EXPORT void
    1.13  razor_set_diff(struct razor_set *set, struct razor_set *upstream,
    1.14  	       razor_diff_callback_t callback, void *data)
    1.15 @@ -698,7 +693,7 @@
    1.16  	struct razor_set *set;
    1.17  	struct razor_set *next;
    1.18  	struct array actions;
    1.19 -	struct install_action *a, *end;
    1.20 +	struct deque *order;
    1.21  };
    1.22  
    1.23  static void
    1.24 @@ -730,6 +725,15 @@
    1.25  				  struct razor_set *next)
    1.26  {
    1.27  	struct razor_install_iterator *ii;
    1.28 +	struct razor_property *prop;
    1.29 +	/* A graph of the actions to be perfomed where
    1.30 +	 * A->B means action A should follow action B.
    1.31 +	 */
    1.32 +	struct graph follows;
    1.33 +	struct install_action *actions, *ai, *aj;
    1.34 +	int i, j, count, vertex_added;
    1.35 +	struct list *link;
    1.36 +	struct razor_set *rs;
    1.37  
    1.38  	assert (set != NULL);
    1.39  	assert (next != NULL);
    1.40 @@ -740,11 +744,58 @@
    1.41  	
    1.42  	razor_set_diff(set, next, add_action, ii);
    1.43  
    1.44 -	ii->a = ii->actions.data;
    1.45 -	ii->end = ii->actions.data + ii->actions.size;
    1.46 +	actions = ii->actions.data;
    1.47 +	count = ii->actions.size / sizeof (struct install_action);
    1.48  
    1.49 -	/* FIXME: We need to figure out the right install order here,
    1.50 -	 * so the post and pre scripts can run. */
    1.51 +	graph_init(&follows);
    1.52 +
    1.53 +	for(i = 0; i < count; i++) {
    1.54 +		ai = actions + i;
    1.55 +		rs = ai->action == RAZOR_INSTALL_ACTION_ADD ? next : set;
    1.56 +		vertex_added = 0;
    1.57 +		link = list_first(&ai->package->properties, &rs->property_pool);
    1.58 +		for(; link; link = list_next(link)) {
    1.59 +			prop = rs->properties.data;
    1.60 +			prop += link->data;
    1.61 +			switch(prop->flags & RAZOR_PROPERTY_TYPE_MASK) {
    1.62 +			case RAZOR_PROPERTY_REQUIRES:
    1.63 +			case RAZOR_PROPERTY_CONFLICTS:
    1.64 +				for(j = 0; j < count; j++) {
    1.65 +					if (j == i)
    1.66 +						continue;
    1.67 +					aj = actions + j;
    1.68 +					if (aj->package->name == prop->name) {
    1.69 +						if (ai->action ==
    1.70 +						    RAZOR_INSTALL_ACTION_ADD)
    1.71 +							graph_add_edge(&follows,
    1.72 +								       i, j);
    1.73 +						else
    1.74 +							graph_add_edge(&follows,
    1.75 +								       j, i);
    1.76 +						vertex_added++;
    1.77 +					}
    1.78 +				}
    1.79 +				break;
    1.80 +			}
    1.81 +		}
    1.82 +		if (ai->action == RAZOR_INSTALL_ACTION_ADD) {
    1.83 +			for(j = 0; j < count; j++) {
    1.84 +				if (j == i)
    1.85 +					continue;
    1.86 +				aj = actions + j;
    1.87 +				if (aj->package == ai->package &&
    1.88 +				    aj->action == RAZOR_INSTALL_ACTION_REMOVE) {
    1.89 +					graph_add_edge(&follows, i, j);
    1.90 +					vertex_added++;
    1.91 +				}
    1.92 +			}
    1.93 +		}
    1.94 +		if (!vertex_added)
    1.95 +			graph_add_edge(&follows, i, i);
    1.96 +	}
    1.97 +
    1.98 +	ii->order = graph_sort(&follows);
    1.99 +	graph_release(&follows);
   1.100  
   1.101  	return ii;
   1.102  }
   1.103 @@ -756,10 +807,12 @@
   1.104  			    enum razor_install_action *action,
   1.105  			    int *count)
   1.106  {
   1.107 -	if (ii->a == ii->end)
   1.108 +	struct install_action *a;
   1.109 +	if (deque_empty(ii->order))
   1.110  		return 0;
   1.111  
   1.112 -	switch (ii->a->action) {
   1.113 +	a = (struct install_action *)ii->actions.data + deque_pop(ii->order);
   1.114 +	switch (a->action) {
   1.115  	case RAZOR_INSTALL_ACTION_ADD:
   1.116  		*set = ii->next;
   1.117  		break;
   1.118 @@ -768,10 +821,9 @@
   1.119  		break;
   1.120  	}
   1.121  
   1.122 -	*package = ii->a->package;
   1.123 -	*action = ii->a->action;
   1.124 +	*package = a->package;
   1.125 +	*action = a->action;
   1.126  	*count = 0;
   1.127 -	ii->a++;
   1.128  
   1.129  	return 1;
   1.130  }
   1.131 @@ -780,5 +832,6 @@
   1.132  razor_install_iterator_destroy(struct razor_install_iterator *ii)
   1.133  {
   1.134  	array_release(&ii->actions);
   1.135 +	deque_free(ii->order);
   1.136  	free(ii);
   1.137  }
     2.1 --- a/test/Makefile.am	Thu May 14 05:51:05 2009 +0100
     2.2 +++ b/test/Makefile.am	Thu May 14 05:55:19 2009 +0100
     2.3 @@ -4,6 +4,7 @@
     2.4  if HAVE_LUA
     2.5    check_SCRIPTS += lua
     2.6  endif
     2.7 +check_SCRIPTS += order
     2.8  
     2.9  relocate:	relocate.sh primary.xml.gz
    2.10  	cp $(srcdir)/relocate.sh relocate
    2.11 @@ -14,6 +15,9 @@
    2.12  remove:	remove.sh primary.xml.gz
    2.13  	cp $(srcdir)/remove.sh remove
    2.14  
    2.15 +order:	order.sh primary.xml.gz
    2.16 +	cp $(srcdir)/order.sh order
    2.17 +
    2.18  lua:	lua.sh primary.xml.gz
    2.19  	cp $(srcdir)/lua.sh lua
    2.20  
    2.21 @@ -39,6 +43,7 @@
    2.22  	zsh.spec		\
    2.23  	zsh2.spec		\
    2.24  	filesystem.spec		\
    2.25 +	order.sh		\
    2.26  	lua.sh			\
    2.27  	remove.sh		\
    2.28  	named-root.sh		\
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/test/order.sh	Thu May 14 05:55:19 2009 +0100
     3.3 @@ -0,0 +1,16 @@
     3.4 +#!/bin/sh
     3.5 +check_file()
     3.6 +{
     3.7 +    if [ ! -e "$RAZOR_ROOT$1" ]; then 
     3.8 +	echo $1: Not in filesystem >&2
     3.9 +	exit 1
    3.10 +    fi
    3.11 +}
    3.12 +export RAZOR_ROOT=`mktemp -dt` || exit 1
    3.13 +../src/razor init || exit 1
    3.14 +export YUM_URL="file://localhost/`pwd`"
    3.15 +../src/razor import-yum || exit 1
    3.16 +../src/razor install zip zsh || exit 1
    3.17 +check_file /usr/var/lib/zip/data.zap
    3.18 +check_file /usr/var/lib/zsh/data.zip
    3.19 +rm -rf "$RAZOR_ROOT"
     4.1 --- a/test/zip.spec	Thu May 14 05:51:05 2009 +0100
     4.2 +++ b/test/zip.spec	Thu May 14 05:55:19 2009 +0100
     4.3 @@ -23,5 +23,35 @@
     4.4  
     4.5  %clean
     4.6  
     4.7 +%pre -p <lua>
     4.8 +function mkdir_missing(dir)
     4.9 +    if posix.stat(dir)==nil then
    4.10 +	posix.mkdir(dir)
    4.11 +    end
    4.12 +end
    4.13 +prefix=posix.getenv("RPM_INSTALL_PREFIX0")
    4.14 +if prefix==nil then
    4.15 +    prefix="/usr"
    4.16 +end
    4.17 +if posix.stat(prefix.."/bin/zap")~=nil then
    4.18 +    mkdir_missing(prefix.."/var")
    4.19 +    mkdir_missing(prefix.."/var/lib")
    4.20 +    posix.mkdir(prefix.."/var/lib/zip")
    4.21 +    io.output(prefix.."/var/lib/zip/data.zap")
    4.22 +    io.write("Important data\n");
    4.23 +    io.close()
    4.24 +end
    4.25 +
    4.26 +%postun -p <lua>
    4.27 +print("zip: postun script\n");
    4.28 +prefix=posix.getenv("RPM_INSTALL_PREFIX0")
    4.29 +if prefix==nil then
    4.30 +    prefix="/usr"
    4.31 +end
    4.32 +if posix.stat(prefix.."/bin/zap")~=nil then
    4.33 +    os.remove(prefix.."/var/lib/zip/data.zap")
    4.34 +    os.remove(prefix.."/var/lib/zip")
    4.35 +end
    4.36 +
    4.37  %files
    4.38  /usr/bin/zip
     5.1 --- a/test/zsh.spec	Thu May 14 05:51:05 2009 +0100
     5.2 +++ b/test/zsh.spec	Thu May 14 05:55:19 2009 +0100
     5.3 @@ -25,6 +25,35 @@
     5.4  
     5.5  %clean
     5.6  
     5.7 +%pre -p <lua>
     5.8 +function mkdir_missing(dir)
     5.9 +    if posix.stat(dir)==nil then
    5.10 +	posix.mkdir(dir)
    5.11 +    end
    5.12 +end
    5.13 +prefix=posix.getenv("RPM_INSTALL_PREFIX0")
    5.14 +if prefix==nil then
    5.15 +    prefix="/usr"
    5.16 +end
    5.17 +if posix.stat(prefix.."/bin/zip")~=nil then
    5.18 +    mkdir_missing(prefix.."/var")
    5.19 +    mkdir_missing(prefix.."/var/lib")
    5.20 +    posix.mkdir(prefix.."/var/lib/zsh")
    5.21 +    io.output(prefix.."/var/lib/zsh/data.zip")
    5.22 +    io.write("Important data\n");
    5.23 +    io.close()
    5.24 +end
    5.25 +
    5.26 +%postun -p <lua>
    5.27 +prefix=posix.getenv("RPM_INSTALL_PREFIX0")
    5.28 +if prefix==nil then
    5.29 +    prefix="/usr"
    5.30 +end
    5.31 +if posix.stat(prefix.."/bin/zip")~=nil then
    5.32 +    os.remove(prefix.."/var/lib/zsh/data.zip")
    5.33 +    os.remove(prefix.."/var/lib/zsh")
    5.34 +end
    5.35 +
    5.36  %files
    5.37  /usr/bin/zsh
    5.38  /etc/zsh.conf