+ if is_function "${umods[i]}_provide" ; then
+ mod=$(${umods[i]}_provide)
+ else
+ mod="${umods[i]}"
+ fi
+ for (( j=0; j<nmods; j++ )); do
+ [[ -z ${MODULES[j]} ]] && continue
+ if [[ ${PROVIDES[j]} == "${mod}" && ${umods[i]} != "${MODULES[j]}" ]] ; then
+ # We don't have a match - now ensure that we still provide an
+ # alternative. This is to handle our preferred modules.
+ for (( l=0; l<nmods; l++ )); do
+ [[ ${l} == "${j}" || -z ${MODULES[l]} ]] && continue
+ if [[ ${PROVIDES[l]} == "${mod}" ]] ; then
+ unset MODULES[j]
+ unset PROVIDES[j]
+ break
+ fi
+ done
+ fi
+ done
+ done
+
+ # Then we strip conflicting modules.
+ # We only need to do this for 3rd party modules that conflict with
+ # our own modules and the preferred list AND the user modules
+ # list doesn't specify a preference.
+ for (( i=0; i<nmods-1; i++ )); do
+ [[ -z ${MODULES[i]} ]] && continue
+ for (( j=i+1; j<nmods; j++)); do
+ [[ -z ${MODULES[j]} ]] && continue
+ [[ ${PROVIDES[i]} == "${PROVIDES[j]}" ]] \
+ && unset MODULES[j] && unset PROVIDES[j]
+ done
+ done
+
+ MODULES=( "${MODULES[@]}" )
+ PROVIDES=( "${PROVIDES[@]}" )
+ return 0
+}
+
+# void modules_sort(void)
+#
+# Sort our modules
+modules_sort() {
+ local i= j= nmods=${#MODULES[@]} m=
+ local -a provide=() provide_list=() after=() dead=() sorted=() sortedp=()
+
+ # Make our provide list
+ for ((i=0; i<nmods; i++)); do
+ dead[i]="false"
+ if [[ ${MODULES[i]} != "${PROVIDES[i]}" ]] ; then
+ local provided=false
+ for ((j=0; j<${#provide[@]}; j++)); do
+ if [[ ${provide[j]} == "${PROVIDES[i]}" ]] ; then
+ provide_list[j]="${provide_list[j]} ${MODULES[i]}"
+ provided=true
+ fi
+ done
+ if ! ${provided}; then
+ provide[j]="${PROVIDES[i]}"
+ provide_list[j]="${MODULES[i]}"
+ fi
+ fi
+ done
+
+ # Create an after array, which holds which modules the module at
+ # index i must be after
+ for ((i=0; i<nmods; i++)); do
+ if is_function "${MODULES[i]}_after" ; then
+ after[i]=" ${after[i]} $(${MODULES[i]}_after) "
+ fi
+ if is_function "${MODULES[i]}_before" ; then
+ for m in $(${MODULES[i]}_before); do
+ for ((j=0; j<nmods; j++)) ; do
+ if [[ ${PROVIDES[j]} == "${m}" ]] ; then
+ after[j]=" ${after[j]} ${MODULES[i]} "
+ break
+ fi
+ done
+ done
+ fi
+ done
+
+ # Replace the after list modules with real modules
+ for ((i=0; i<nmods; i++)); do
+ if [[ -n ${after[i]} ]] ; then
+ for ((j=0; j<${#provide[@]}; j++)); do
+ after[i]="${after[i]// ${provide[j]} / ${provide_list[j]} }"
+ done
+ fi
+ done
+
+ # We then use the below code to provide a topologial sort
+ module_after_visit() {
+ local name="$1" i= x=
+
+ for ((i=0; i<nmods; i++)); do
+ [[ ${MODULES[i]} == "$1" ]] && break