Ignore:
Timestamp:
01/28/2018 05:56:55 PM (7 years ago)
Author:
Pierre Labastie <pierre@…>
Branches:
ablfs-more, legacy, trunk
Children:
1fa0dee
Parents:
764a5d7
Message:

New management of dependencies:

  • Even if only required or recommended deps only are requested and built, account for optional deps to build the pacakge order
  • build "runtime" deps after the pacakge dependening on them, but before any other package
  • using the "first" role in the book, implement pass1 pacakges when there are circular dependencies
  • Documentation has still to be written
  • There must be bugs, thank you for testing...
File:
1 edited

Legend:

Unmodified
Added
Removed
  • BLFS/libs/func_dependencies

    r764a5d7 r2140f22  
    44#
    55
    6 #---------------------------------------------------------------------------#
    7 # This is a set of (recursive) functions for manipulating a dependency      #
    8 # tree. Everything would be "simple" without circular dependencies. We      #
    9 # would just have to build the tree using the packages.xml file, and to     #
    10 # provide a function for browsing it. But we need to be able to detect      #
    11 # circular dependencies and to possibly change the tree depending on        #
    12 # priorities. This is why we keep with each node a record of the path       #
    13 # from the root to the node, which we call *link* and a record of the       #
    14 # successive priorities which we call *priolink*.                           #
     6#-----------------------------------------------------------------------------#
     7# This is a set of (recursive) functions for manipulating a dependency graph. #
     8# We use algorithms and definitions from chapter 4 (mainly section 4.2) of    #
     9# https://algs4.cs.princeton.edu/. The graph we manipulate is the directed    #
     10# graph of the dependencies: nodes are packages in the BLFS book. A node A is #
     11# connected to a node B if package A depends on B. A topological order (rev-  #
     12# erted) is exactly what we want for a build order. But a topological order   #
     13# only exists if the graph is acyclic. We'll therefore have to remove cycles. #
     14# There are a number of other features we want to consider:                   #
     15# - edges are weighted according to the dependency requirement:               #
     16#   1 for required                                                            #
     17#   2 for recommended                                                         #
     18#   3 for optional                                                            #
     19#   4 for external                                                            #
     20#   We should consider only edges with weight lower or equal to that          #
     21#   specified by the user, but see below.                                     #
     22# - we do not want to build the whole book. The user specifies a set of       #
     23#   packages, and we have to consider only nodes reachable from this set      #
     24#   using edges of weight not exceeding the specified weight.                 #
     25# - when doing the topological sort, we want to consider all the edges and    #
     26#   not only those not exceeding the specified weight: If a package A in the  #
     27#   reachable subgraph depends optionally on another package B in the same    #
     28#   subgraph, we want to build B before A. But this means we'll have to       #
     29#   remove cycles for all weights.                                            #
     30# - dependencies have another qualifier: before or after. The problem: if a   #
     31#   package A depends on B with an "after" qualifier, and a package C depends #
     32#   on A with a "before" qualifier, C may need B to be able to use A. So the  #
     33#   only safe way to consider "after" qualifiers is to consider that they are #
     34#   "before" deps for any parent of the packages considered.                  #
     35# We'll therefore have a 3 pass procedure. First build the set of nodes       #
     36# reachable from the root set. Second, remove dangling edges (those pointing  #
     37# to packages outside the node set), and move "after" edges to "before" edges #
     38# originating from the parents. Third remove cycles and generate a            #
     39# topological sort.                                                           #
     40#                                                                             #
     41# TODO: document each pass
     42# Data layout:                                                                #
     43# TODO: needs also to document the .tree files, and the "f" qualifier
     44#                                                                             #
     45# A node of the tree is represented by a text file <nodeName>.dep. Each edge  #
     46# starting from this node is represented by a line in this file. We keep      #
     47# those files in the same directory. We introduce a special node named root,  #
     48# whose edges point to the list of nodes requested by the user. Each line     #
     49# contains three fields:                                                      #
     50#  - the weight of the edge                                                   #
     51#  - the "before" (b) or "after" (a) qualifier                                #
     52#  - the name of the destination of the edge                                  #
    1553#                                                                           #
    16 # Layout of the tree:                                                       #
    17 #                                                                           #
    18 # A node of the tree is represented by a file <nodeName>.dep. We keep all   #
    19 # those files in the same directory. The root node file is "root.dep".      #
    20 # Files <nodeName>.dep have the following layout:                           #
    21 #   - the first line is the link: the link is an array of numbers           #
    22 #     (n1 n2 ... nN), describing the path from the root to <nodeName>: n1   #
    23 #     is the position of the first node of the path in root.dep, n2 is the  #
    24 #     position of the second node of the path in <node1>.dep and so on. The #
    25 #     link is not needed for normal tree operations (building a subtree or  #
    26 #     browsing the tree), but it allows to check whether a dependency is    #
    27 #     circular, and to find its parent.                                     #
    28 #   - the second line is an array of priorities (p1 p2 ... pN), giving the  #
    29 #     priority (1=required, 2=recommended, 3=optional) of each dependency   #
    30 #     in the link.                                                          #
    31 #   - each subsequent line is of the form "p <depname>", where p is the     #
    32 #     priority as above, and <depname> is the name of the dependency. The   #
    33 #     position which is recorded in the link is the number of the line      #
    34 #     minus 2.                                                              #
    35 #                                                                           #
     54# TODO: The following is obsolete
    3655# Circular dependencies:                                                    #
    3756#                                                                           #
     
    5271# A string of spaces for indenting:
    5372declare -a spaceSTR="                                                                   "
    54 # When we are backing up from a circular dependency, `exchange_triplet'
    55 # shall contain (parent dependency_0 dependency_n):
    56 declare -a exchange_triplet
     73# When we are backing up from a circular dependency, `parentNode'
     74# contains the node which has an edge entering the cycle
     75declare parentNode
     76
     77#---------------------#
     78generate_subgraph() { #
     79#---------------------#
     80: <<inline_doc
     81    function:   Create a subgraph of all the nodes reachable from the node
     82                represented by the file whose name is $1. The edges considered
     83                are those with maximal weight DEP_LEVEL (recursive function).
     84    input vars: $1 : file name corresponding to the node whose edges will be
     85                     followed for the DFS
     86                $2 : weight of the edge leading to this node
     87                $3 : depth (root is 1)
     88                $4 : qualifier (a for after, b for before)
     89    externals:  vars:  DEP_LEVEL   contains 1 if we want to build the
     90                                   tree only for required dependencies,
     91                                   2 if we want also recommended ones,
     92                                   3 if we want also optional ones, but only
     93                                   for the requested packages,
     94                                   4 if we want all the dependencies
     95                       MAIL_SERVER contains the name of the MTA we want to use.
     96                files: ../xsl/dependencies.xsl: stylesheet for creating the
     97                                               .dep files
     98                       ../packages.xml:         File containing packages id
     99                                                and dependencies
     100    returns:    0 if the tree has been successfully created
     101    output:     files: for each node reachable from $1, a file <node>.dep.
     102    on error:   nothing
     103    on success: nothing
     104inline_doc
     105
     106local depFile=$1
     107local -i weight=$2
     108local -i depth=$3
     109local qualifier=$4
     110local -i spacing=0
     111local priostring
     112local buildstring
     113local id_of_dep
     114local prio_of_dep
     115local build_of_dep
     116local dep_level
     117
     118if (( depth < 10 )); then spacing=1; fi
     119case $weight in
     120    1) priostring=required    ;;
     121    2) priostring=recommended ;;
     122    3) priostring=optional    ;;
     123esac
     124case $qualifier in
     125    a) buildstring=runtime ;;
     126    b) buildstring=        ;;
     127esac
     128dep_level=$DEP_LEVEL
     129if [ "$dep_level" = 3 ] && [ "$depth" -gt 2 ]; then dep_level=2; fi
     130if [ "$dep_level" -gt 3 ]; then dep_level=3; fi
     131echo -en "\nNode: $depth${spaceSTR:0:$(( depth + spacing ))}${RED}${depFile%.dep}${OFF} $priostring $buildstring"
     132
     133depth=$(( depth + 1 ))
     134if (( depth < 10 )); then spacing=1; else spacing=0; fi
     135# Start of loop
     136{
     137while read prio_of_dep build_of_dep id_of_dep; do
     138case $prio_of_dep in
     139    1) priostring=required ;;
     140    2) priostring=recommended ;;
     141    3) priostring=optional ;;
     142    4) priostring=external ;;
     143esac
     144case $build_of_dep in
     145    a) buildstring=runtime ;;
     146    b) buildstring=        ;;
     147esac
     148# Has this entry already been seen
     149  if [ -f ${id_of_dep}.dep ] ; then
     150# Just display it and proceed.
     151    echo -en "\nEdge: $depth${spaceSTR:0:$((depth + spacing))}${MAGENTA}${id_of_dep}${OFF} $priostring $buildstring"
     152    continue
     153  fi
     154# Is the weight higher than requested?
     155  if [ "$prio_of_dep" -gt $dep_level ]; then
     156# Just display it and proceed.
     157    echo -en "\n Out: $depth${spaceSTR:0:$((depth + spacing))}${YELLOW}${id_of_dep}${OFF} $priostring $buildstring"
     158    continue
     159  fi
     160# Otherwise, let's build the corresponding subgraph.
     161  xsltproc --stringparam idofdep "$id_of_dep" \
     162           --stringparam MTA "$MAIL_SERVER"   \
     163           -o ${id_of_dep}.dep                \
     164           ../xsl/dependencies.xsl ../packages.xml
     165
     166  if [[ -s ${id_of_dep}.dep ]]; then # this dependency has dependencies
     167    generate_subgraph ${id_of_dep}.dep $prio_of_dep $depth $build_of_dep
     168  else # id_of_dep has no dependencies, just touch the file and display
     169    touch ${id_of_dep}.dep
     170    echo -en "\nLeaf: $depth${spaceSTR:0:$((depth + spacing))}${CYAN}${id_of_dep}${OFF} $priostring $buildstring"
     171  fi
     172done
     173} <$depFile
     174depth=$(( depth - 1 ))
     175if (( depth < 10 )); then spacing=1; else spacing=0; fi
     176echo -en "\n End: $depth${spaceSTR:0:$((depth + spacing))}${GREEN}${depFile%.dep}${OFF}"
     177return 0
     178}
     179
     180#-----------#
     181path_to() { #
     182#-----------#
     183: <<inline_doc
     184    function:   check whether there is a path from $1 to $2 on the graph
     185    input       vars: $1 contains the filename of the starting node.
     186                      $2 contains the name of the node to reach
     187                      $3 contains the weight above which we do not want to
     188                         follow an edge
     189                      "seen" (global) contains the list of already seen nodes
     190    returns:    0 if the node has been found
     191                1 if not
     192    on error:   nothing
     193    on success: nothing
     194inline_doc
     195local start=$1
     196local seek=$2
     197local prio=$3
     198local prio_of_dep
     199local build_of_dep
     200local id_of_dep
     201local r
     202
     203if test "${start%.dep}" = "$seek"; then return 0; fi
     204seen="$seen$file "
     205if test -s $file; then
     206  {
     207  while read prio_of_dep build_of_dep id_of_dep; do
     208    if test "$prio" -lt "$prio_of_dep"; then continue; fi
     209    if test "${seen% $id_of_dep *}" = "$seen"; then continue; fi
     210    if path_to ${id_of_dep}.dep $seek $prio; then return 0; fi
     211  done
     212  } < $start
     213fi
     214return 1
     215}
     216#------------------#
     217clean_subgraph() { #
     218#------------------#
     219: <<inline_doc
     220    function:   Remove dangling edges and create groups of deps for "after"
     221                deps: A-before->B-after->C becomes:
     222                 A -before-> Bgroupxx -before-> B
     223                                     \
     224                                      -before-> C
     225                the name of the group is chosen so that it is unlikely as
     226                a package name (so that it is removed when building the
     227                xml book).
     228    input       vars: None
     229                files: <node>.dep files containing dangling edges and
     230                       "after" qualifiers
     231    returns:    0
     232    output:     files: <node>.dep files containing no dangling edges and
     233                       no "after" qualifiers
     234    on error:   nothing
     235    on success: nothing
     236inline_doc
     237
     238local node
     239local id_of_dep
     240local prio_of_dep
     241local build_of_dep
     242local lines_to_remove
     243local lines_to_change
     244local parent
     245local p
     246local b
     247local start
     248local seen
     249
     250for node in $(ls *.dep); do
     251  if test $node = root.dep; then continue; fi
     252  lines_to_remove=
     253  {
     254  while read prio_of_dep build_of_dep id_of_dep; do
     255    if ! test -f ${id_of_dep}.dep; then
     256      lines_to_remove="$lines_to_remove $id_of_dep"
     257      continue
     258    fi
     259  done
     260  } <$node
     261  for id_of_dep in $lines_to_remove; do
     262    sed "/\ $id_of_dep\$/d" -i $node
     263  done
     264done
     265for node in $(grep -l ' a ' *.dep); do
     266  lines_to_remove=
     267  if ! [ -e ${node%.dep}groupxx.dep ]; then
     268    for parent in $(grep -l ${node%.dep}\$ *); do
     269      p=0
     270      for start in $(grep ' a ' $node | cut -d' ' -f3); do
     271        seen=" "
     272        if path_to ${start}.dep ${parent%.dep} 3; then p=1; break; fi
     273      done
     274      if test $p = 0; then
     275        sed -i "s/\ ${node%.dep}\$/&groupxx/" $parent
     276      fi
     277    done
     278    echo "1 b ${node%.dep}" > ${node%.dep}groupxx.dep
     279  fi
     280  {
     281  while read prio_of_dep build_of_dep id_of_dep; do
     282    if test $build_of_dep = a; then
     283      if ! grep -q ${id_of_dep} ${node%.dep}groupxx.dep; then
     284        echo "$prio_of_dep b ${id_of_dep}" >> ${node%.dep}groupxx.dep
     285      fi
     286      lines_to_remove="$lines_to_remove $id_of_dep"
     287    fi
     288  done
     289  } <$node
     290  for id_of_dep in $lines_to_remove; do
     291    sed "/\ $id_of_dep\$/d" -i $node
     292  done
     293done
     294for node in $(grep -l ' f ' *); do
     295  lines_to_change=
     296  {
     297  while read prio_of_dep build_of_dep id_of_dep; do
     298    if test $build_of_dep = f; then
     299      if ! test -f ${id_of_dep}-pass1.dep; then
     300        cp ${id_of_dep}{,-pass1}.dep;
     301      fi
     302      lines_to_change="$lines_to_change $id_of_dep"
     303      unset lr
     304      {
     305      while read p b start; do
     306        seen=" "
     307        if path_to ${start}.dep ${node%.dep} $p; then
     308          lr="$lr $start"
     309        fi
     310      done
     311      } < ${id_of_dep}-pass1.dep
     312      for p in $lr; do
     313        sed "/\ $p\$/d" -i ${id_of_dep}-pass1.dep
     314      done
     315    fi
     316  done
     317  } <$node
     318  for id_of_dep in $lines_to_change; do
     319    sed "/\ $id_of_dep\$/"'{s/ f / b /;s/$/-pass1/}' -i $node
     320  done
     321done
     322} # End clean_subgraph
    57323
    58324#----------------------------#
     
    63329                (recursive function)
    64330    input vars: $1 : file with a list of targets (child nodes)
    65                      the first line of the file is the link
     331                     the first line of the file is the link
    66332                $2 : priority (1=req, 2=rec, 3=opt)
    67     externals:  vars:  DEP_LEVEL   contains 1 if we want to build the
    68                                    tree only for required dependencies,
    69                                    2 if we want also recommended ones,
    70                                    and 3 if we want optional ones too.
    71                        MAIL_SERVER contains the name of the MTA we want to use.
    72                 files: ../xsl/dependencies.xsl: stylesheet for creating the
    73                                                .dep files
    74                        ../packages.xml:         File containing packages id
    75                                                 and dependencies
    76333    returns:    0 if the tree has been successfully created
    77334                1 if we are backing up to the parent of a circular dep
    78     modifies:   vars: exchange_triplet contains the triplet when return is 1
     335                  and there are only required deps in the cycle
     336                2 if we are backing up to the parent of a circular dep
     337                  and there are recommended deps and no optional deps in the
     338                  cycle
     339                3 if we are backing up to the parent of a circular dep
     340                  and there are optiional deps in the cycle
     341    modifies:   vars: ParentNode is set when return is not 0
    79342    output:     files: for each <pkg> with dependencies in $1,
    80                        a file <pkg>.dep and its dependencies
     343                       a file <pkg>.tree and its dependencies
    81344    on error:   nothing
    82345    on success: nothing
    83346inline_doc
    84347
    85 local DepFile=$1
     348local depFile=$1
    86349local priority=$2
    87350local -a rootlink
     
    91354local -i count=0
    92355local id_of_dep
     356local build_of_dep
     357local prio_of_dep
    93358local parent
    94359local lines_to_remove=
    95360local srootlink
    96 local dep_level
    97361local priostring
    98362local dpriostring
     
    100364
    101365{
    102 # We use fd number 6 for input from DepFile, because we need 0 for user input
    103 read -u6 -a rootlink
     366read -a rootlink
    104367depth=${#rootlink[*]}
    105 read -u6 -a priolink
    106 dep_level=$DEP_LEVEL
    107 # For now, process optional deps only for the root packages.
    108 if (( $DEP_LEVEL > 2 )) && (( $depth > 1 )); then dep_level=2; fi
     368read -a priolink
    109369srootlink="${rootlink[*]} "
    110370case $priority in
     
    112372    2) priostring=recommended ;;
    113373    3) priostring=optional ;;
    114     4) priostring=external ;;
    115374esac
    116 # start of DepFile
    117 echo -en "\nNode: $depth${spaceSTR:0:$depth}${RED}$DepFile${OFF} $priostring"
    118 
    119 while read -u6 prio_of_dep id_of_dep; do
    120 case $prio_of_dep in
     375# start of depFile
     376echo -en "\nNode: $depth${spaceSTR:0:$depth}${RED}${depFile%.tree}${OFF} $priostring"
     377
     378while read prio_of_dep build_of_dep id_of_dep; do
     379  case $prio_of_dep in
    121380    1) dpriostring=required ;;
    122381    2) dpriostring=recommended ;;
    123382    3) dpriostring=optional ;;
    124     4) dpriostring=external ;;
    125 esac
     383  esac
    126384# count entries in file
    127385  (( count++ ))
    128386# Has this entry already been seen?
    129   if [ -f ${id_of_dep}.dep ]; then # found ${id_of_dep}.dep already in tree
    130     otherlink=($(head -n 1 ${id_of_dep}.dep))
     387  if [ -f ${id_of_dep}.tree ]; then # found ${id_of_dep}.tree already in tree
     388    otherlink=($(head -n 1 ${id_of_dep}.tree))
    131389    if [ -z "${otherlink[*]}" ]
    132       then echo otherlink empty for $id_of_dep.dep
     390      then echo otherlink empty for $id_of_dep.tree
    133391      echo This should not happen, but happens to happen...
    134392      exit 1
    135393    fi
    136 # Do not use "${rootlink[*]}" =~ "${otherlink[*]}": case rootlink=(1 11)
     394#Do not use "${rootlink[*]}" =~ "${otherlink[*]}": case rootlink=(1 11)
    137395# and otherlink=(1 1)
    138396    if [[ ${srootlink#"${otherlink[*]} "} != ${srootlink} ]]; then # cir. dep
    139397      echo -en "\nCirc: $((depth+1))${spaceSTR:0:$((depth+1))}${YELLOW}${id_of_dep}${OFF} $dpriostring"
    140 # First look for the other parent of this dependency.
    141 # The parent has the same link without the last entry.
    142 # We do not need otherlink anymore so just destroy the last element
    143       unset otherlink[-1]
    144       parent=$(grep ^"${otherlink[*]}"\$ -l *)
    145       parent=${parent%.dep}
    146 # Find lowest priority in branch from parent to DepFile:
     398# Find lowest priority in branch from parent to depFile:
    147399      p2=0
    148400      for (( i=${#otherlink[*]}; i < $depth ; i++ )) ; do
     
    151403      if (( $prio_of_dep >= $p2 )); then # prune
    152404        lines_to_remove="$lines_to_remove $id_of_dep"
    153         sed -i "/$id_of_dep/d" ${DepFile/.dep/.odep}
    154       else #backup with prio priority
    155         exchange_triplet=($parent $id_of_dep ${DepFile%.dep})
    156         return $priority
     405        sed -i "/$id_of_dep/d" ${depFile/.tree/.dep}
     406      else # find and set parent, then return lowest priority
     407# The parent has the same link without the last entry.
     408# We do not need otherlink anymore so just destroy the last element
     409        unset otherlink[-1]
     410        parentNode=$(grep ^"${otherlink[*]}"\$ -l *)
     411        return $p2
    157412      fi
    158     else # not circular: prune tree (but not .odep, since it may happen that
     413    else # not circular: prune tree (but not .dep, since it may happen that
    159414         # the tree is destroyed and rebuilt in another order)
    160415      lines_to_remove="$lines_to_remove $id_of_dep"
     
    163418             # subtree computed. We are done
    164419  fi # Has this entry already been seen?
    165 # So, this entry has not already been seen.
    166 # If this is an external dep, just display it and go to next dep:
    167   if [ "$prio_of_dep" -eq 4 ]; then
    168     echo "${rootlink[*]} $count" > ${id_of_dep}.dep
     420# So, this entry has not already been seen. Let's build the corresponding
     421# subtree. First check there is a subtree...
     422# Use -s, because it may happen that after removing lines, .dep exists
     423# but is empty.
     424  if [[ -s ${id_of_dep}.dep ]]; then # this dependency has dependencies
     425    sed "1i${rootlink[*]} $count\\
     426${priolink[*]} $prio_of_dep" < ${id_of_dep}.dep \
     427                             > ${id_of_dep}.tree # add link and priolink
     428    generate_dependency_tree ${id_of_dep}.tree $prio_of_dep
     429# Test return value, in case we exchange dependencies
     430    p2=$?
     431    case $p2 in
     432     0) # Normal return
     433       ;;
     434     $prio_of_dep) # we remove this dep, but since it may become unreachable,
     435                   # move it to be built later (as a dep of parent).
     436         tree_erase ${id_of_dep}.tree
     437         lines_to_remove="$lines_to_remove $id_of_dep"
     438         sed -i "/${id_of_dep}/d" ${depFile/.tree/.dep}
     439         echo "$prio_of_dep b $id_of_dep" >> $parentNode
     440# must be added to .dep in case parentNode is destroyed when erasing
     441# the tree
     442         echo "$prio_of_dep b $id_of_dep" >> ${parentNode/.tree/.dep}
     443         continue
     444       ;;
     445     *) # We are backing up
     446         return $p2
     447       ;;
     448    esac
     449  else # id_of_dep has no dependencies, just record the link in a file
     450       # and print
     451    echo "${rootlink[*]} $count" > ${id_of_dep}.tree
    169452    echo -en "\nLeaf: $(($depth+1))${spaceSTR:0:$(($depth+1))}${CYAN}${id_of_dep}${OFF} $dpriostring"
    170     continue
    171   fi
    172 # Otherwise, let's build the corresponding
    173 # subtree. Since decisions about circular deps can lead us to start again
    174 # dependencies, we restart until the flag is false.
    175   flag=true
    176   while [ $flag = true ]; do
    177     flag=false
    178     if [ ! -f "${id_of_dep}.odep" ]; then
    179       xsltproc --stringparam dependencies ${dep_level} \
    180         --stringparam idofdep $id_of_dep \
    181         --stringparam MTA $MAIL_SERVER   \
    182         -o ${id_of_dep}.odep \
    183         ../xsl/dependencies.xsl ../packages.xml
    184     fi
    185 
    186 # Use -s, because it may happen that after removing lines, .odep exists
    187 # but is empty.
    188     if [[ -s ${id_of_dep}.odep ]]; then # this dependency has dependencies
    189       sed "1i${rootlink[*]} $count\\
    190 ${priolink[*]} $prio_of_dep" < ${id_of_dep}.odep \
    191                              > ${id_of_dep}.dep # add link and priolink
    192       generate_dependency_tree ${id_of_dep}.dep $prio_of_dep
    193 # Test return value, in case we exchange dependencies
    194       p2=$?
    195       case $p2 in
    196        0) # Normal return
    197          ;;
    198        [123]) # We are backing up to parent
    199          if [[ ${exchange_triplet} == ${DepFile%.dep} ]] ; then
    200 # We are the parent!
    201 # First, we have to find the parent of our new direct dep, and remove
    202 # the new direct dep from the parent.odep:
    203            otherlink=($(head -n1 ${exchange_triplet[2]}.dep))
    204            unset otherlink[-1]
    205            parent=$(grep -l ^"${otherlink[*]}"\$ *.dep)
    206            sed -i /[[:digit:]]\ ${exchange_triplet[2]}\$/d ${parent/.dep/.odep}
    207            tree_erase ${id_of_dep}.dep
    208 # We want that our direct dep be ${exchange_triplet[2]} and that id_of_dep
    209 # be pulled in as an indirect dep, so exchange.
    210 # Just doing a sed -i "s@${id_of_dep}@${exchange_triplet[2]}@" $DepFile
    211 # is not good if $DepFile contains several times the same line
    212 # so first find the first line and then sed
    213            lineno=$(sed -n /${id_of_dep}/= $DepFile | head -n1)
    214            sed -i "${lineno}s@${id_of_dep}@${exchange_triplet[2]}@" $DepFile
    215 # Do the same for the odep file:
    216            local OdepFile=${DepFile/.dep/.odep}
    217            lineno=$(sed -n /${id_of_dep}/= $OdepFile | head -n1)
    218            sed -i "${lineno}s@${id_of_dep}@${exchange_triplet[2]}@" $OdepFile
    219            id_of_dep=${exchange_triplet[2]}
    220            flag=true # we have to regenerate the tree for the new dependency
    221          else
    222 # We are not the parent. If our priority is greater than p2
    223 # we have to change the triplet and return priority, else return current p2.
    224 # echo (DEBUG) backing up to ${exchange_triplet} at ${DepFile%.dep}
    225            if (( $priority > $p2 )); then
    226              exchange_triplet[2]=${DepFile%.dep}
    227              return $priority
    228            else
    229              return $p2
    230            fi
    231          fi
    232          ;;
    233       esac
    234     else # id_of_dep has no dependencies, just record the link in a file
    235          # and print
    236       echo "${rootlink[*]} $count" > ${id_of_dep}.dep
    237       echo -en "\nLeaf: $(($depth+1))${spaceSTR:0:$(($depth+1))}${CYAN}${id_of_dep}${OFF} $dpriostring"
    238     fi
    239   done
    240 done
    241 echo -en "\n End: $depth${spaceSTR:0:$depth}${GREEN}$DepFile${OFF}"
    242 } 6<$DepFile
     453  fi
     454done
     455echo -en "\n End: $depth${spaceSTR:0:$depth}${GREEN}${depFile%.tree}${OFF}"
     456} <$depFile
    243457# It may happen that a file is created with several times
    244458# the same line. Normally, all those lines but one
     
    250464# that line
    251465for line in $lines_to_remove
    252   do lineno=$(sed -n /^[[:digit:]]\ $line\$/= $DepFile | tail -n1)
    253   sed -i ${lineno}d $DepFile
     466  do lineno=$(sed -n /^[[:digit:]]\ b\ $line\$/= $depFile | tail -n1)
     467  sed -i ${lineno}d $depFile
    254468done
    255469return 0
    256470}
     471
    257472
    258473#---------------#
     
    265480for f in $(grep '[^0-9 ]' $file | sed 's/.* //'); do
    266481#  echo f=$f
    267   if grep -q '[^0-9 ]' ${f}.dep ; then
    268     tree_browse ${f}.dep
     482  if grep -q '[^0-9 ]' ${f}.tree ; then
     483    tree_browse ${f}.tree
    269484  fi
    270485  echo $f
     
    283498rootlink="$(head -n1 $file) "
    284499for f in $(grep '[^0-9 ]' $file | sed 's/.* //'); do
    285   if [ -f ${f}.dep ]; then
    286     rootlink2="$(head -n1 ${f}.dep) "
     500  if [ -f ${f}.tree ]; then
     501    rootlink2="$(head -n1 ${f}.tree) "
    287502# We want two things:
    288503# i)  do not erase the file if it is in another branch
     
    294509    if [[ ${rootlink2#${rootlink}} != ${rootlink2} &&
    295510          ${rootlink#${rootlink2}} == ${rootlink} ]] ; then
    296       tree_erase ${f}.dep
     511      tree_erase ${f}.tree
    297512    fi
    298513  fi
Note: See TracChangeset for help on using the changeset viewer.