d607ac3717
When the .dep file is scanned during the tree building, it outputs dependencies in the file order, while when the tree is scanned later, dependencies are output in alphabetical order. This may eventually lead to a wrong order at the end. To be sure that both output are the same, just sort the .dep file before scanning it.
197 lines
6.2 KiB
Bash
197 lines
6.2 KiB
Bash
#!/bin/bash
|
|
#
|
|
# $Id$
|
|
#
|
|
|
|
# A string of spaces for indenting:
|
|
declare -a spaceSTR=" "
|
|
declare -a exchange_triplet
|
|
|
|
# In case we find a cirdular dependency, it has the form :
|
|
# parent->dependency_0->...->dependency_n->dependency_0
|
|
# If we want to build dependency_n before dependency_0,
|
|
# no problem: we just prune the tree at dependency_n.
|
|
# If we want to build first dependency_0, we need to
|
|
# put dependency_n as a dependency of parent. The triplet
|
|
# above shall contain (parent dependency_0 dependency_n)
|
|
|
|
#----------------------------#
|
|
generate_dependency_tree() { #
|
|
#----------------------------#
|
|
: <<inline_doc
|
|
function: Create a subtree of the dependency tree
|
|
(recursive function)
|
|
input vars: $1 : file with a list of targets
|
|
the first line of the file is an array
|
|
of links
|
|
externals: vars: BLFS_XML
|
|
DEP_LEVEL
|
|
modifies: vars: none
|
|
returns: nothing
|
|
output: files: for each pkg with dependencies in $1,
|
|
a file pkg.dep and its dependencies
|
|
on error: nothing
|
|
on success: nothing
|
|
inline_doc
|
|
|
|
local DepFile=$1
|
|
local -a rootlink
|
|
local -a otherlink
|
|
local -i depth
|
|
local -i count=0
|
|
local id_of_dep
|
|
local parent
|
|
local lines_to_remove=
|
|
local srootlink
|
|
local dep_level
|
|
|
|
{
|
|
# BEWARE : the order of options matters : read -a -u6 rootlink hangs forever
|
|
# (actually, the doc says -a array -u fd)
|
|
# We use fd number 6 for input from DepFile, because we need 0 for user input
|
|
read -u6 -a rootlink
|
|
depth=${#rootlink[*]}
|
|
dep_level=$DEP_LEVEL
|
|
if (( $DEP_LEVEL > 2 )) && (( $depth > 1 )); then dep_level=2; fi
|
|
srootlink="${rootlink[*]} "
|
|
# start of Depfile
|
|
echo -en "\nNode: $depth${spaceSTR:0:$depth}${RED}$DepFile${OFF}"
|
|
|
|
while read -u6 id_of_dep; do
|
|
# count entries in file
|
|
(( count++ ))
|
|
# Has this entry already been seen?
|
|
if [ -f ${id_of_dep}.dep ]; then # found ${id_of_dep}.dep already in tree
|
|
otherlink=($(head -n 1 ${id_of_dep}.dep))
|
|
if [ -z "${otherlink[*]}" ]
|
|
then echo otherlink empty for $id_of_dep.dep
|
|
echo This should not happen, but happens to happen...
|
|
exit 1
|
|
fi
|
|
# Do not use "${rootlink[*]}" =~ "${otherlink[*]}": case rootlink=(1 11)
|
|
# and otherlink=(1 1)
|
|
if [[ ${srootlink#"${otherlink[*]} "} != ${srootlink} ]]; then # circular dep
|
|
# First look for the other parent of this dependency.
|
|
# The parent has the same link without the last entry.
|
|
# We do not need otherlink anymore so just destroy the last element
|
|
unset otherlink[${#otherlink[*]}-1]
|
|
parent=$(grep ^"${otherlink[*]}"\$ -l *)
|
|
parent=${parent%.dep}
|
|
echo -en "\nCirc: $depth${spaceSTR:0:$depth}${BLUE}Circular dependency detected:${OFF}"
|
|
echo -en "\nCirc: $depth${spaceSTR:0:$depth}${BOLD}${id_of_dep}${OFF} is a dependency \
|
|
of ${BOLD}${parent}${OFF}"
|
|
echo -en "\nCirc: $depth${spaceSTR:0:$depth}${BOLD}${DepFile%.dep}${OFF} is a dependency \
|
|
of ${BOLD}${id_of_dep}${OFF}"
|
|
echo -en "\nCirc: $depth${spaceSTR:0:$depth}${BOLD}${id_of_dep}${OFF} is a dependency \
|
|
of ${BOLD}${DepFile%.dep}${OFF}"
|
|
# If idofdep is the parent of DepFile, we can exchange them if required
|
|
# if grep -q ${DepFile%.dep} ${id_of_dep}.dep; then
|
|
# we propose exchange always
|
|
echo -en "\nCirc: $depth${spaceSTR:0:$depth}Do you want to build ${id_of_dep} first? yes/no (no):"
|
|
read ANSWER
|
|
if [ x$ANSWER = "xyes" ] ; then # exchange:
|
|
# set triplet and return 1
|
|
exchange_triplet=($parent $id_of_dep ${DepFile%.dep})
|
|
return 1
|
|
else # no exchange: prune
|
|
lines_to_remove="$lines_to_remove $id_of_dep"
|
|
fi
|
|
# else
|
|
# lines_to_remove="$lines_to_remove $id_of_dep"
|
|
# fi
|
|
else # not circular: prune
|
|
lines_to_remove="$lines_to_remove $id_of_dep"
|
|
fi
|
|
continue
|
|
fi
|
|
flag=true
|
|
while [ $flag = true ]; do
|
|
flag=false
|
|
xsltproc --stringparam dependencies ${dep_level} \
|
|
--stringparam idofdep $id_of_dep \
|
|
-o ${id_of_dep}.dep \
|
|
../xsl/dependencies.xsl ../packages.xml
|
|
|
|
if [[ -f ${id_of_dep}.dep ]]; then
|
|
sort ${id_of_dep}.dep -o ${id_of_dep}.dep
|
|
sed -i "1i${rootlink[*]} $count" ${id_of_dep}.dep
|
|
generate_dependency_tree ${id_of_dep}.dep
|
|
# Test return value, in case we exchange dependencies
|
|
case $? in
|
|
0) # Normal return
|
|
;;
|
|
1) # We are backing up to parent
|
|
if [[ ${exchange_triplet} == ${DepFile%.dep} ]]
|
|
then tree_erase ${id_of_dep}.dep
|
|
# Just doing a sed -i "s@${id_of_dep}@${exchange_triplet[2]}@" $DepFile
|
|
# is not good if $DepFile contains several times the same line
|
|
# so first find the first line and then sed
|
|
lineno=$(sed -n /${id_of_dep}/= $DepFile | head -n1)
|
|
sed -i "${lineno}s@${id_of_dep}@${exchange_triplet[2]}@" $DepFile
|
|
id_of_dep=${exchange_triplet[2]}
|
|
flag=true
|
|
else
|
|
# echo backing up to ${exchange_triplet} at ${DepFile%.dep}
|
|
return 1
|
|
fi
|
|
;;
|
|
esac
|
|
else
|
|
echo "${rootlink[*]} $count" > ${id_of_dep}.dep
|
|
fi
|
|
done
|
|
done
|
|
echo -en "\n End: $depth${spaceSTR:0:$depth}${GREEN}$DepFile${OFF}"
|
|
} 6<$DepFile
|
|
# It may happen that a file is created with several times
|
|
# the same line. Normally, all those lines but one
|
|
# would be flagged to be removed (or all of them if
|
|
# the dependency appeared before). a simple sed /$line/d
|
|
# destroys all the lines. We should instead remove
|
|
# only one for each appearance of it in lines_to_remove.
|
|
# so first get the number of first line and then delete
|
|
# that line
|
|
for line in $lines_to_remove
|
|
do lineno=$(sed -n /^$line\$/= $DepFile | head -n1)
|
|
sed -i ${lineno}d $DepFile
|
|
done
|
|
return 0
|
|
}
|
|
|
|
#---------------#
|
|
tree_browse() { #
|
|
#---------------#
|
|
local file=$1
|
|
local f
|
|
|
|
#echo file=$file
|
|
for f in $(grep '[^0-9 ]' $file); do
|
|
# echo f=$f
|
|
if grep -q '[^0-9 ]' ${f}.dep ; then
|
|
tree_browse ${f}.dep
|
|
fi
|
|
echo $f
|
|
done
|
|
}
|
|
|
|
#--------------#
|
|
tree_erase() { #
|
|
#--------------#
|
|
local file=$1
|
|
local f
|
|
local -a rootlink
|
|
local -a rootlink2
|
|
|
|
#echo file=$file
|
|
rootlink=($(head -n1 $file))
|
|
for f in $(grep '[^0-9 ]' $file); do
|
|
# echo " f"=$f
|
|
if [ -f ${f}.dep ]; then
|
|
rootlink2=($(head -n1 ${f}.dep))
|
|
if [[ "${rootlink2[*]}" =~ "${rootlink[*]}" ]] ; then
|
|
tree_erase ${f}.dep
|
|
fi
|
|
fi
|
|
done
|
|
rm -f $file
|
|
}
|