/var/lib/sorcery/modules/libdepends
1 #!/bin/bash
2 #---------------------------------------------------------------------
3 ## @Synopsis Functions for dealing with dependencies as a non-cyclic directed graph. Since that's such a mouthful, it will simply be referred to as a tree, even though it's not.
4 ## @Copyright (C) 2002 The Source Mage Team <http://www.sourcemage.org>
5 ## A spell is represented as a node containing some pieces of data
6 ## seperated by colons.
7 ## spell:dependent spell:on/off:type:casting_flag:is_a_target_flag
8 ## @Contributers Chris Brien (christopher_brien@hotmail.com)
9 ## @Contributers Paul Mahon (pmahon@sourcemage.org)
10 #---------------------------------------------------------------------
11
12 #
13 # conceptual function call tree...perhaps this will enlighten sorcery
14 # students..
15 #
16 # compute_uninstalled_depends (the entry point)
17 # -> for each spell (this list grows during processing)
18 # -> run PREPARE
19 # -> run CONFIGURE
20 # -> run DEPENDS
21 # -> depends|runtime_depends <spell> (external)
22 # -> work_depends_spell
23 # -> private_common_depends -> libstate.add_depends
24 # -> add to NEW_DEPENDS
25 # -> libstate.add_depends
26 # -> optional_depends|suggest_depends <spell> (external)
27 # -> work_optional_depends_spell
28 # -> query
29 # -> private_common_depends -> libstate.add_depends
30 # -> add to NEW_DEPENDS
31 # -> libstate.add_depends
32 # -> depends|runtime_depends <provider> (external)
33 # -> work_depends_provider
34 # -> select provider
35 # -> private_common_depends -> libstate.add_depends
36 # -> add to NEW_DEPENDS
37 # -> libstate.add_depends
38 # -> optional_depends|suggest_depends <provider> (external)
39 # -> work_optional_depends_provider
40 # -> select provider
41 # -> private_common_depends
42 # -> add to NEW_DEPENDS
43 # -> libstate.add_depends
44 # -> private_add_depends
45 # -> update hash tables and lists from NEW_DEPENDS
46 #
47 # in other words, for every spell run its external files
48 # and then deal with their callbacks (depends and optional_depends)
49 # each of those calls eventually arrives at a dependency rule
50 # which is stored somewhere through libstate calls , and in an internal
51 # variable (NEW_DEPENDS). After we finish all the files we bundle up
52 # our new information and move to the next spell.
53 #
54
55 # Surprise env vars:
56 # SPELL: this is actually locally defined somewhere up the call stack
57 # but from most function's point of view it should be there...
58 # COMPILE: set in cast. It means that the main">main">main">main">main spells should be recompiled
59 # RECONFIGURE: set in cast. I means that the info in the state depends should
60 # be disregarded and replaced.
61 # PRETEND_NOT_INSTALLED: set here. It is a list of spells that are to be
62 # recompiled, so they should not be treated as installed.
63 # CAST_HASH: The name of the hast table to put spells and dependencies
64 # that are to be cast (only used in this lib)
65 # BACK_HASH: reverse of CAST_HASH will be used to handle failures
66 # more gracefully someday...
67 # CANNOT_CAST: The name of the hash table to put spells that cannot be cast
68 # and the reason why. Usualy because they are exiled or don't exist
69 # (only used in this lib)
70
71
72 ######################BEGIN CALLS TO OUTSIDE WORLD########################
73
74 #---------------------------------------------------------------------
75 ## Run the spell's PREPARE script if it exists
76 ## @param Spell to prepare
77 ## @Globals SCRIPT_DIRECTORY
78 #---------------------------------------------------------------------
79 function run_prepare()
80 {
81 local SPELL=$1
82
83 debug "cast" "run_prepare() - SPELL = $SPELL SCRIPT_DIRECTORY = $SCRIPT_DIRECTORY"
84
85 depends_message "${SPELL}" "preparing environment..."
86
87 # these are here so you can source section/grimoire level scripts in
88 # PREPARE, which by definition runs before the spell is loaded
89 # and they are defined as usual (see bug 8329)
90 codex_get_spell_paths "$SCRIPT_DIRECTORY"
91
92 local PROTECT_SORCERY=yes
93 run_spell_file PREPARE prepare
94 rc=$?
95 return $rc
96 }
97
98 #---------------------------------------------------------------------
99 ## This will be home to all "other" questions we are supposed to ask about
100 ## during this phase of things, right now its a placeholder
101 ## @param Spell
102 #---------------------------------------------------------------------
103 function run_other() {
104 local SPELL=$1
105 # ask the questions about xinetd/initd script installation
106 persistent_load &&
107 query_services &&
108 query_custom_cflags &&
109 query_conflicts &&
110 run_security &&
111 persistent_save ||
112 {
113 persistent_clear
114 log_failure_reason run_other #remove this if all the previous callers get one
115 return 1
116 }
117 #ask about other stuff
118
119 }
120
121 #---------------------------------------------------------------------
122 ## Run the spell's CONFIGURE script if it exists
123 ## @param Spell to configure
124 #---------------------------------------------------------------------
125 function run_configure() {
126 local SPELL=$1
127 debug "cast" "run_configure() - SCRIPT_DIRECTORY = $SCRIPT_DIRECTORY"
128
129 function run_configure_msg() {
130 depends_message "${SPELL}" "running configuration..."
131 }
132
133 local PROTECT_SORCERY=yes
134 run_spell_file CONFIGURE configure run_configure_msg
135 rc=$?
136 return $rc
137 }
138
139 #---------------------------------------------------------------------
140 ## Run a spell's DEPENDS if it exists
141 ## @param Spell
142 #---------------------------------------------------------------------
143 function run_depends() {
144 local SPELL=$1
145 debug "cast" "run_depends() - SCRIPT_DIRECTORY = $SCRIPT_DIRECTORY"
146
147 function run_depends_msg() {
148 depends_message "${SPELL}" "checking dependencies..."
149 }
150
151 local PROTECT_SORCERY=yes
152 run_spell_file DEPENDS depends run_depends_msg
153 rc=$?
154 return $rc
155 }
156
157 #---------------------------------------------------------------------
158 ## Run a spell's UP_TRIGGERS if it exists
159 ## @param Spell
160 #---------------------------------------------------------------------
161 function run_up_triggers() {
162 local SPELL=$1
163 debug "cast" "run_up_triggers() - SCRIPT_DIRECTORY = $SCRIPT_DIRECTORY"
164
165 function run_up_triggers_msg() {
166 depends_message "${SPELL}" "checking for reverse triggers..."
167 }
168 local PROTECT_SORCERY=yes
169 run_spell_file UP_TRIGGERS up_triggers run_up_triggers_msg
170 rc=$?
171 return $rc
172 }
173
174 #---------------------------------------------------------------------
175 ## process any sub-depends the current spell is going to provide
176 ## These come from the live sub-depends table and from spells that
177 ## have already been processed
178 #---------------------------------------------------------------------
179 function run_our_sub_depends() {
180 $STD_DEBUG
181 local sub_depends pair
182 # do all sub-depends on us from live-table first, they get priority
183 # in case there is a conflict
184 for triple in $(search_sub_depends "$SUB_DEPENDS_STATUS" '.*' "$SPELL") ; do
185 # parse the line out, eventually these silly variable expansions should
186 # be in functions or benchmarked against explode
187 tmp=${triple%:*};
188 requester=${tmp%:*};
189 sub_dependee=${tmp#*:};
190 sub_depends=${triple##*:}
191
192 # if the requester has been processed skip any sub-depends its
193 # previous instance requested, bug 11865
194 local hash_depends_looked_at
195 hash_get_ref "depends_looked_at" "$requester" hash_depends_looked_at
196 [[ $hash_depends_looked_at == done ]] && continue
197
198 process_sub_depends "$requester" "$sub_dependee" "$sub_depends" || return 1
199 done
200
201 # do all sub-depends from sub_dep_r_hash (things that we provide)
202 for pair in $(hash_get sub_dep_r_hash $SPELL) ; do
203 requester=${pair%:*}
204 sub_depends=${pair#*:}
205
206 process_sub_depends "$requester" "$SPELL" "$sub_depends" || return 1
207 done
208 }
209
210 #---------------------------------------------------------------------
211 ## run any sub-depends that we requested on behalf of the sub-dependee
212 #---------------------------------------------------------------------
213 function run_other_sub_depends() {
214 $STD_DEBUG
215 local this_spell=$1
216 local SPELL sub_dependee sub_depends pair
217 local sub_dependee_looked_at
218 # do all sub-depends from sub_dep_f_hash (things we request)
219 for pair in $(hash_get sub_dep_f_hash $this_spell) ; do
220 # FIXME, do this one spell at a time, rather than in whatever order we
221 # see them it will reduce the number of run_details
222 sub_dependee=${pair%:*}
223 sub_depends=${pair#*:}
224 hash_get_ref depends_looked_at $sub_dependee sub_dependee_looked_at
225 if [[ $sub_dependee_looked_at == done ]]; then
226 # load the spell and clear out any special variables
227 SPELL=$sub_dependee
228 run_details
229 local NEW_SUB_DEPENDEES=""
230 # afk 5-28-06: bash 3.0 breaks local foo=(), have to make this two lines
231 local NEW_DEPENDS; NEW_DEPENDS=()
232 local NEW_RUNTIME_DEPENDS; NEW_RUNTIME_DEPENDS=()
233 process_sub_depends "$this_spell" "$sub_dependee" "$sub_depends" ||
234 return 1
235
236 # this is needed in case processing the sub-depends added a depends
237 # isnt this fun?
238 private_add_depends
239 fi
240 done
241 }
242
243 #---------------------------------------------------------------------
244 ## Run a spell's SUB_DEPENDS file for a specific sub-depends.
245 ## This is idempotent, if a sub-depends has already been processed it will
246 ## not run the SUB_DEPENDS file again.
247 ##
248 ## Expects the sub-dependee to be loaded.
249 ## If the spell does not have a SUB_DEPENDS file, it is a failure.
250 #---------------------------------------------------------------------
251 function process_sub_depends() {
252 $STD_DEBUG
253 local requester=$1
254 local sub_dependee=$2
255 local sub_depends=$3
256 local PROTECT_SORCERY=yes
257
258 if test -x $SCRIPT_DIRECTORY/SUB_DEPENDS; then
259 if ! list_find "$(hash_get processed_sub_depends $sub_dependee)" "$sub_depends"; then
260 local rc=0
261
262 local THIS_SUB_DEPENDS=$sub_depends
263 local PROCESSED_SUB_DEPENDS
264 hash_get_ref processed_sub_depends $sub_dependee PROCESSED_SUB_DEPENDS
265 run_spell_file SUB_DEPENDS sub_depends || return 1
266 hash_append processed_sub_depends $sub_dependee $sub_depends
267 else
268 debug libdepends "SUB_DEPENDS: $sub_dependee needs to provide $sub_depends but has already been processed"
269 fi
270 else
271 # sub-depends file doesnt exist, something messed up somewhere
272 return 1
273 fi
274 # add the information to the uncommitted depends file
275 local sub_depends_file rsub_depends_file
276 get_uncommitted_sub_depends_file "$sub_dependee" sub_depends_file || return 1
277 add_sub_depends "$sub_depends_file" "$requester" "$sub_dependee" "$sub_depends"
278 get_uncommitted_rsub_depends_file "$requester" rsub_depends_file || return 1
279 add_sub_depends "$rsub_depends_file" "$requester" "$sub_dependee" "$sub_depends"
280 }
281
282 ######################END CALLS TO OUTSIDE WORLD########################
283
284 #---------------------------------------------------------------------
285 ## Create a map of spells to their dependent spells.
286 ## Then for all installed or held spells, output a libhash command to
287 ## join the spell name and dependency info.
288 ## Then evaluate the output, thus filling a libhash with dependency info.
289 ## @param Name of hash table to put dependencies
290 #---------------------------------------------------------------------
291 function compute_installed_depends() {
292 #$1==hash table to fill
293 local hash=$1
294 touch $DEPENDS_STATUS $SPELL_STATUS &>/dev/null
295
296 local pattern status
297 if [[ $2 ]] ; then
298 pattern="required|optional|runtime|suggest"
299 else
300 pattern="required|optional"
301 fi
302 status=${3:-on}
303
304 # From here forward $1 and $2 are only used to refer to awk variables
305
306 lock_file "$DEPENDS_STATUS"
307 lock_file "$SPELL_STATUS"
308 # sub(/(.*)/, "", $2) removes a provider name
309 eval $(awk -v pattern="$pattern" -v status="$status" -F : 'BEGIN {
310 while (getline < ARGV[1] ) {
311 if( $3==status && ( $4 ~ pattern ) ) {
312 sub(/\(.*\)/, "", $2);
313 depmap[$1]=depmap[$1]" "$2" "
314 }
315 }
316 while (getline < ARGV[2] ) {
317 if( $3=="installed" || $3=="held") {
318 printf("hash_put $hash %s \"%s\";\n",$1,depmap[$1]);
319 }
320 }
321 }' $DEPENDS_STATUS $SPELL_STATUS )
322 unlock_file "$DEPENDS_STATUS"
323 unlock_file "$SPELL_STATUS"
324 }
325
326 #---------------------------------------------------------------------
327 ## Create a map of spells to their dependent spells.
328 ## Then for all installed or held spells, output a libhash command to
329 ## join the spell name and dependency info.
330 ## Then evaluate the output, thus filling a libhash with dependency info.
331 ## @param Name of hash table to fill with dependencies
332 #---------------------------------------------------------------------
333 function compute_reverse_installed_depends() {
334 #$1==hash table to fill
335 local hash=$1
336 touch $DEPENDS_STATUS $SPELL_STATUS &>/dev/null
337
338 local pattern status
339 if [[ $2 ]] ; then
340 pattern="required|optional|runtime|suggest"
341 else
342 pattern="required|optional"
343 fi
344 status=${3:-on}
345
346 # From here forward $1 and $2 are only used to refer to awk variables
347
348 lock_file "$DEPENDS_STATUS"
349 lock_file "$SPELL_STATUS"
350 # sub(/(.*)/, "", $2) removes a provider name
351 eval $(awk -v pattern="$pattern" -v status="$status" -F : 'BEGIN {
352 while (getline < ARGV[1] ) {
353 if( $3==status && ( $4 ~ pattern ) ) {
354 sub(/\(.*\)/, "", $2);
355 depmap[$2]=depmap[$2]" "$1" "
356 }
357 }
358 while (getline < ARGV[2] ) {
359 if( $3=="installed" || $3=="held") {
360 printf("hash_put $hash %s \"%s\";\n",$1,depmap[$1]);
361 }
362 }
363 }' $DEPENDS_STATUS $SPELL_STATUS )
364 unlock_file "$DEPENDS_STATUS"
365 unlock_file "$SPELL_STATUS"
366 }
367
368 #---------------------------------------------------------------------
369 ## calling this will accomplish several things:
370 ## <ol>
371 ## <li> most importantly it finds the closure of all spells that need to
372 ## be cast
373 ## <li> it builds a hash table mapping spells to their depends, possibly by
374 ## asking the user for input
375 ## <li> it updates DEPENDS_STATUS, arguably it shouldn't be doing this.
376 ## </ol>
377 ##
378 ## What happens: take all the spells we've been asked to resolve
379 ## for each one of them run its details file
380 ## the details file will call back to depends/optional_depends
381 ## at this point we determine/find/query for depends info
382 ## update the hash table, update DEPENDS_STATUS, and append to the
383 ## list of spells to resolve
384 ##
385 ## @param Hashtable name for dependencies
386 ## @param Hashtable name for spells with problem in resolution (or something)
387 ## @param Hashtable name for spells which cannot cast
388 #---------------------------------------------------------------------
389 function compute_uninstalled_depends()
390 {
391
392 # $1=table to place spells in
393 # $2=table to put problem spells in, $* = root spells
394
395 debug "libdepends" "compute_depends of $*"
396 local CAST_HASH="$1"
397 local BACK_CAST_HASH="$2"
398 local CANNOT_CAST_HASH="$3"
399 BONUS_SPELLS=()
400 shift 3
401 local spell spells
402 spells=( $@ )
403
404 PRETEND_NOT_INSTALLED=" $@ "
405
406 local _idx
407 local looked_at
408
409 # this is a list of all spells basesystem depends on it is used to
410 # avoid loops with the "everything depends on basesystem" feature
411 local base_deps
412 base_deps=$(search_depends_status $DEPENDS_STATUS basesystem|cut -f2 -d:)
413
414 # All specified spells are assumed to be not installed, or else -c and -r
415 # would have to be specified all the time.
416
417 for (( _idx=0 ; _idx<${#spells[*]} ; _idx++ )) ; do
418 hash_get_ref depends_looked_at ${spells[$_idx]} looked_at
419 if [[ ! $looked_at ]]; then
420 if ! private_run_depends ${spells[$_idx]} ; then
421 # i dont know if this will work, but it will have to suffice
422 private_remove_dependees ${spells[$_idx]}
423 fi
424 else
425 debug "libdepends" "already looked at ${spells[$_idx]}, skipping"
426 fi
427 done
428 # we no longer need these, no sense in keeping them around
429 hash_unset depends_looked_at
430 hash_unset sub_dep_f_hash
431 hash_unset sub_dep_r_hash
432 hash_unset sub_depends_process
433 hash_unset processed_sub_depends
434
435 # we need this so processes on the other side of make know whats going on
436 hash_export uncommitted_hash
437
438 BONUS_SPELLS=( ${BONUS_SPELLS[*]} ${UP_DEPENDS[*]} )
439 }
440
441 #---------------------------------------------------------------------
442 ## A private function for running a spell's DEPENDS script.
443 ## No functions except libdepends functions should use this.
444 ## @param Spell
445 #---------------------------------------------------------------------
446 function private_run_depends()
447 {
448 debug "libdepends" "$FUNCNAME - $*"
449 local SPELL=$1
450
451 # special accumulators for the current spell
452 local NEW_DEPENDS=""
453 local NEW_SUB_DEPENDEES=""
454 local NEW_RUNTIME_DEPENDS=""
455 local NEW_UP_DEPENDS=""
456 local triggerees=""
457 local spell_depends
458 local spell_sub_depends
459
460 hash_put "depends_looked_at" "$SPELL" "start"
461
462 # We only need to run the stuff if we are going to be casting.
463 # It only needs to be added to the casting hash table if we are
464 # really casting it
465 if private_should_cast $SPELL ; then
466
467 # this cant go in private_should_cast because then the dependee wont
468 # have a chance at being fixed
469 # we check already here, so a specified spell isn't needlessly run
470 if spell_exiled $1; then
471 depends_message "${SPELL}" "is exiled and will not be cast."
472 log_failure_reason exiled $1
473 return 1
474 fi
475 get_uncommitted_depends_file $SPELL spell_depends
476 spell_sub_depends=$spell_depends.sub
477 if [ -n "$RECONFIGURE" ]; then
478 local t_abandonded_p
479 rm -f $DEPENDS_CONFIG/$SPELL
480 test -f $DEPENDS_CONFIG/$SPELL.p &&
481 mkdir -p $ABANDONED_PERSIST &&
482 lock_file "$DEPENDS_CONFIG/$SPELL.p" &&
483 lock_start_transaction "$ABANDONED_PERSIST/$SPELL.p" t_abandonded_p &&
484 mv -f "$DEPENDS_CONFIG/$SPELL.p" "$t_abandonded_p" &&
485 unlock_file "$DEPENDS_CONFIG/$SPELL.p" &&
486 lock_commit_transaction "$ABANDONED_PERSIST/$SPELL.p"
487 fi
488 prepare_spell_config
489 SCRIPT_DIRECTORY=`codex_find_spell_by_name $SPELL`
490 run_prepare $SPELL &&
491 run_details &&
492 run_configure $SPELL &&
493 run_other $SPELL &&
494 run_depends $SPELL &&
495 run_up_triggers $SPELL &&
496 run_our_sub_depends $SPELL &&
497
498 # possibly recast things that depend on us if option is set (-B)
499 private_upward_depends $SPELL &&
500 private_recast_optionals $SPELL &&
501 private_add_triggerees &&
502 private_add_depends ||
503 { debug "libdepends" "$FUNCNAME failed to process $SPELL." ; return 1; }
504 # no point in keeping the file around if its empty...
505 test -s $spell_depends || rm -f $spell_depends $spell_sub_depends
506
507 if real_list_find "${RUNTIME_DEPENDS[*]}" "$SPELL"; then
508 local k=${#BONUS_SPELLS[@]}
509 BONUS_SPELLS[$k]=$SPELL
510 fi
511
512 # this processes any sub-depends we requested and the sub-dependee
513 # has already been processed, so we must process them on their behalf
514 # this must be done after everything else!
515 run_other_sub_depends "$SPELL" || return 1
516 else
517 depends_message "${SPELL}" "No work to do."
518 hash_put "depends_looked_at" "$SPELL" "ignore"
519 fi
520
521 # if there weren't any depends no sense in keeping the file around
522 return 0
523 }
524
525 #---------------------------------------------------------------------
526 ## Decides if a spell should be cast, or if we can leave it alone.
527 ## Check if the spell is installed, or if theres some other reason to
528 ## rebuild it.
529 ## @param Spell
530 #---------------------------------------------------------------------
531 function private_should_cast()
532 {
533 local each
534 # order is important here...
535 if ! codex_does_spell_exist $1; then
536 return 1
537 elif real_list_find "$PRETEND_NOT_INSTALLED" $1 ; then
538 # always look at stuff on the command line unless its exiled
539 return 0
540 # from here on the spell was not on the command line...
541 elif spell_held $1; then
542 # don't recast held even with -R
543 return 1
544 elif [[ "$RECAST_DOWN" ]] ; then
545 # user gave -R so recast...
546 return 0
547 elif real_list_find "${UP_DEPENDS[*]}" $1; then
548 # if someone has determined this is an upward depend (-B)
549 return 0
550 elif real_list_find "${TRIGGEREES[*]}" $1; then
551 # if its being triggered we need to look at it, despite its
552 # installed status
553 return 0
554 elif real_list_find "${FORCE_DEPENDS[*]}" $1; then
555 return 0
556 elif [[ "$(hash_get sub_depends_process $1)" != "" ]] ; then
557 return 0
558 elif spell_installed $1 ; then
559 # returns success if want to cast
560 want_lazy_update $1 && return 0 || return 1
561 fi
562
563 # we must need to install this as we know nothing else about it
564 return 0
565 }
566 #---------------------------------------------------------------------
567 ## @param Spell name
568 ## Find all the spells that depend on the spell given as $1
569 #---------------------------------------------------------------------
570 function private_upward_depends() {
571 if [[ "$RECAST_UP" ]] ; then
572 local tmp
573 # Note, use the reverse depends tree for this when we get a chance
574 # and/or move the weird pattern into library functions...
575 # (afrayedknot 2005-10-02)
576 lock_file "$DEPENDS_STATUS"
577 tmp=$(grep "^.*:$1\(([^:]*)\)\?:" $DEPENDS_STATUS|cut -f1 -d:|tr "\n" " ")
578 unlock_file "$DEPENDS_STATUS"
579 local j k each
580 let j=${#NEW_UP_DEPENDS[*]}
581 for each in $tmp; do
582 NEW_UP_DEPENDS[$j]=$each
583 let j++
584 done
585 spells=( ${spells[*]} ${tmp} )
586 fi
587 }
588
589 # shared code for both loops in private_recast_optionals
590 private_recast_optionals_sub() {
591 local spell="$1"
592 local message="$2"
593
594 enabled=""
595 message "$message"
596 if [[ $RECAST_OPTIONALS == always ]]; then
597 enabled=yes
598 else
599 local default=n
600 [[ $RECAST_OPTIONALS == ask-yes ]] && default=y
601 if query "Recast $spell with the dependency enabled?" $default; then
602 enabled=yes
603 fi
604 fi
605 }
606
607 #---------------------------------------------------------------------
608 ## Find spells that optionally depended on the current spell but had the
609 ## dependency disabled, ask if the user wants to recast the spell.
610 ## Also finds disabled features that the current spell is a provider of.
611 #---------------------------------------------------------------------
612 function private_recast_optionals() {
613 if [[ $RECAST_OPTIONALS ]] && [[ $RECAST_OPTIONALS != ignore ]] ; then
614 local spell j enabled
615 let j=${#NEW_UP_DEPENDS[*]}
616 for spell in $(search_depends_status_exact $DEPENDS_STATUS \
617 '.*' "$1\(([^:]*)\)\?" off optional '.*' '.*'|cut -f1 -d:); do
618 private_recast_optionals_sub $spell \
619 "$spell has a disabled optional dependency on $1"
620 if [[ $enabled ]] ; then
621 NEW_UP_DEPENDS[$j]=$spell
622 let j++
623 # toggle the dependency, so the user doesn't get requeried
624 toggle_depends_status $DEPENDS_STATUS $spell "$1(\([^:]*\))?"
625 spells=( ${spells[*]} $spell )
626 fi
627 done
628
629 # also check for disabled features that $1 is a provider of
630 local features feature_regex
631 # get the features and build a regex for quicker lookup
632 features=$(codex_find_spell_provides $1)
633 for feature in $features; do
634 feature_regex="$feature\|$feature_regex"
635 done
636 feature_regex=${feature_regex%\\|}
637 for spell in $(search_depends_status_exact $DEPENDS_STATUS \
638 '.*' "($feature_regex)" off optional '.*' '.*'|cut -f1 -d:|sort -u); do
639 private_recast_optionals_sub $spell \
640 "$spell has a disabled optional dependency on $1 as a provider"
641 if [[ $enabled ]] ; then
642 NEW_UP_DEPENDS[$j]=$spell
643 let j++
644 # toggle all the features that $1 provides and set $1 as their provider
645 for feature in $features; do
646 change_spell_provider $DEPENDS_STATUS $spell "$1" "$feature" "on"
647 done
648 spells=( ${spells[*]} $spell )
649 fi
650 done
651 fi
652 }
653
654 ###################BEGIN CALLBACKS FROM OUTSIDE#######################
655
656 #---------------------------------------------------------------------
657 ## @param spell or provider name
658 ## @param addition to OPTS
659 ## @param description
660 ## @param grimoires to look in
661 ## Delegates provider and spell cases to different worker functions.
662 ## and gets grimoires if necessary for cross grimoire depends
663 ##
664 ## Called by real_depends and real_runtime_depends
665 #---------------------------------------------------------------------
666 function real_generic_required_depends()
667 {
668 local failure_ok=$1
669 local article=$2
670 local query_term=$3
671 local database_term=$4
672 shift 4
673
674 if [[ "$1" == "-sub" ]] ; then
675 local requested_sub_depends=$2
676 shift 2
677 fi
678
679 if [[ $1 != ${1/ /} ]] ; then
680 message "${PROBLEM_COLOR}Spell names must not contain spaces:" \
681 "${DEFAULT_COLOR}${SPELL_COLOR}$1${DEFAULT_COLOR}"
682 return 1
683 fi
684
685 # determine if we're dealing with a provider or a spell
686 local is_provider
687 if ! codex_does_spell_exist $1 &> /dev/null; then
688 is_provider=yes
689 fi
690
691 # see if theres another grimoire
692 if [[ "$4" ]] && ! [[ "$OVERRIDE_GRIMOIRES" ]] ; then
693 local grimoire here nothere current
694
695 for grimoire in $4; do
696 if [[ "$grimoire" == "current" ]] ; then
697 current=yes
698 elif codex_find_grimoire "$grimoire" > /dev/null; then
699 list_add here $grimoire
700 else
701 list_add nothere $grimoire
702 fi
703 done
704 if [[ "$here" ]] || [[ "$current" ]] ; then
705 if [[ "$nothere" ]] ; then
706 depends_message "$SPELL" "has $article $query_term on${is_provider+ some}" "$1" "from $4."
707 message "${SPELL_COLOR}$1${DEFAULT_COLOR}${CHECK_COLOR}" \
708 "exists in the following grimoires${DEFAULT_COLOR}" \
709 "${SPELL_COLOR}${4}${DEFAULT_COLOR}${CHECK_COLOR}"
710 message "You dont have ${SPELL_COLOR}$nothere${DEFAULT_COLOR}" \
711 "${CHECK_COLOR}but you have ${SPELL_COLOR}$here${DEFAULT_COLOR}"
712 for grimoire in $nothere ; do
713 if query "Get $grimoire grimoire?" n; then
714 scribe add "$grimoire"
715 unset GRIMOIRE_DIR[*]
716 source $GRIMOIRE_LIST
717 if codex_find_grimoire "$grimoire" > /dev/null; then
718 list_add here $grimoire
719 else
720 message "${PROBLEM_COLOR}Failed to get grimoire${DEFAULT_COLOR}"
721 fi
722 fi
723 done
724 # else
725 # have all the grimoires, nothing to do, this is probably the case most
726 # of the time
727 fi
728 else
729 if [[ "$nothere" ]] ; then
730 depends_message "$SPELL" "has $article $query_term on${is_provider+ some}" "$1" "from $4."
731 message "${CHECK_COLOR}You dont have any of the grimoires" \
732 "${SPELL_COLOR}$4${DEFAULT_COLOR}${CHECK_COLOR}."
733 message "You must add at least one grimoire to satisfy the" \
734 "dependency.${DEFAULT_COLOR}"
735 for grimoire in $nothere ; do
736 if query "Get $grimoire grimoire?" n; then
737 scribe add "$grimoire"
738 unset GRIMOIRE_DIR[*]
739 source $GRIMOIRE_LIST
740 if codex_find_grimoire "$grimoire" > /dev/null; then
741 list_add here $grimoire
742 else
743 message "${PROBLEM_COLOR}Failed to get grimoire${DEFAULT_COLOR}"
744 fi
745 fi
746 done
747 else
748 # this is a bug, most likely with list_add in order for this
749 # to happen, there has to be some grimoires to look in, and the
750 # grimoires are neither installed nor uninstalled
751 message "This is a bug, probably with list_add, please contact the" \
752 "sorcery team, thanks."
753 return 1
754 fi
755 fi
756 if [[ ! $here ]] && [[ ! $current ]] ; then
757 message "${PROBLEM_COLOR}no grimoire for $1 was retrieved${DEFAULT_COLOR}"
758 if [[ $failure_ok == "no" ]] || ! query "Build $1 anyway?" y; then
759 return 1
760 fi
761 fi
762 fi
763
764 local target_spell
765 if [[ $is_provider ]]; then
766 work_depends_provider "$failure_ok" "$article" \
767 "$query_term" "$database_term" "$@" &&
768 if [[ "$requested_sub_depends" ]]; then
769 target_spell=$(get_spell_provider "$SPELL" "$1")
770 fi
771 else
772 work_depends_spell "$failure_ok" "$article" \
773 "$query_term" "$database_term" "$@" &&
774 target_spell=$1
775 fi &&
776 for sub_depend in $requested_sub_depends; do
777 sub_depends "$target_spell" "$sub_depend" || return 1
778 done
779 }
780
781
782 #---------------------------------------------------------------------
783 ## Passthrough to real_generic_required_depends, specifies the
784 ## parts that differ from runtime depends
785 #---------------------------------------------------------------------
786 function real_depends() {
787 real_generic_required_depends "no" "a" "dependency" "required" "$@"
788 }
789
790 #---------------------------------------------------------------------
791 ## Passthrough to real_generic_required_depends, specifies the
792 ## parts that differ from required depends
793 #---------------------------------------------------------------------
794 function real_runtime_depends() {
795 real_generic_required_depends "yes" "a" "runtime dependency" "runtime" "$@"
796 }
797
798
799 #---------------------------------------------------------------------
800 ## @param spell or provider name
801 ## @param addition to OPTS if enabled
802 ## @param addition to OPTS if disabled
803 ## @param description
804 ## @param grimoires to look in
805 ## Delegates provider and spell cases to different worker functions.
806 ##
807 ## Called by real_depends and real_runtime_depends
808 #---------------------------------------------------------------------
809 function real_generic_optional_depends()
810 {
811 local failure_ok=$1
812 local article=$2
813 local query_term=$3
814 local database_term=$4
815 shift 4
816
817 if [[ "$1" == "-sub" ]] ; then
818 local requested_sub_depends=$2
819 shift 2
820 fi
821
822 if [[ $1 != ${1/ /} ]] ; then
823 message "${PROBLEM_COLOR}Spell names must not contain spaces:" \
824 "${DEFAULT_COLOR}${SPELL_COLOR}$1${DEFAULT_COLOR}"
825 return 1
826 fi
827
828 # determine if we're dealing with a provider or a spell
829 local is_provider
830 if ! codex_does_spell_exist $1 &> /dev/null; then
831 is_provider=yes
832 fi
833
834 # see if theres another grimoire
835 if [[ "$5" ]] && ! [[ "$OVERRIDE_GRIMOIRES" ]] ; then
836 local grimoire here nothere current
837 for grimoire in $5; do
838 if [[ "$grimoire" == "current" ]] ; then
839 current=yes
840 elif codex_find_grimoire "$grimoire" > /dev/null; then
841 list_add here $grimoire
842 else
843 list_add nothere $grimoire
844 fi
845 done
846 if [[ "$here" ]] || [[ "$current" ]] ; then
847 if [[ "$nothere" ]] ; then
848 depends_message "$SPELL" "has $article $query_term on${is_provider+ some}" "$1" "from $5."
849 message "${SPELL_COLOR}$1${DEFAULT_COLOR}${CHECK_COLOR}" \
850 "exists in the following grimoires${DEFAULT_COLOR}" \
851 "${SPELL_COLOR}${5}${DEFAULT_COLOR}${CHECK_COLOR}"
852 message "You dont have ${SPELL_COLOR}$nothere${DEFAULT_COLOR}" \
853 "${CHECK_COLOR}but you have ${SPELL_COLOR}$here${DEFAULT_COLOR}"
854 for grimoire in $nothere ; do
855 if query "Get $grimoire grimoire?" n; then
856 scribe add "$grimoire"
857 unset GRIMOIRE_DIR[*]
858 source $GRIMOIRE_LIST
859 if codex_find_grimoire "$grimoire" > /dev/null; then
860 list_add here $grimoire
861 else
862 message "${PROBLEM_COLOR}Failed to get grimoire${DEFAULT_COLOR}"
863 fi
864 fi
865 done
866 # else
867 # have all the grimoires, nothing to do, this is probably the case most
868 # of the time
869 fi
870 else
871 if [[ "$nothere" ]] ; then
872 depends_message "$SPELL" "has $article $query_term on${is_provider+ some}" "$1" "from $5."
873 message "${CHECK_COLOR}You dont have any of the grimoires" \
874 "${SPELL_COLOR}${5}${DEFAULT_COLOR}${CHECK_COLOR}."
875 for grimoire in $nothere ; do
876 if query "Get $grimoire grimoire?" n; then
877 scribe add "$grimoire"
878 unset GRIMOIRE_DIR[*]
879 source $GRIMOIRE_LIST
880 if codex_find_grimoire "$grimoire" > /dev/null; then
881 list_add here $grimoire
882 else
883 message "${PROBLEM_COLOR}Failed to get grimoire${DEFAULT_COLOR}"
884 fi
885 fi
886 done
887 else
888 # this is a bug, most likely with list_add in order for this
889 # to happen, there has to be some grimoires to look in, and the
890 # grimoires are neither installed nor uninstalled
891 message "This is a bug, probably with list_add, please contact the" \
892 "sorcery team, thanks."
893 return 1
894 fi
895 fi
896 if [[ ! $here ]] && [[ ! $current ]] ; then
897 message "${PROBLEM_COLOR}no grimoire for $1 was retrieved${DEFAULT_COLOR}"
898 message "Assuming dependency is off because it could not be met"
899 if [[ $is_provider ]]; then
900 private_common_depends "($1)" "off" "$database_term" "$2" "$3"
901 else
902 private_common_depends "$1" "off" "$database_term" "$2" "$3"
903 fi
904 return 0
905 fi
906 fi
907
908 local target_spell
909 if [[ $is_provider ]]; then
910 work_optional_depends_provider "$failure_ok" "$article" \
911 "$query_term" "$database_term" "$@" &&
912 if [[ "$requested_sub_depends" ]]; then
913 target_spell=$(get_spell_provider "$SPELL" "$1")
914 fi
915 else
916 work_optional_depends_spell "$failure_ok" "$article" \
917 "$query_term" "$database_term" "$@" &&
918 target_spell=$1
919 fi &&
920 if [[ "$requested_sub_depends" ]] &&
921 [[ "$target_spell" ]] &&
922 is_depends_enabled "$SPELL" "$target_spell"; then
923 for sub_depend in $requested_sub_depends; do
924 sub_depends "$target_spell" "$sub_depend" || return 1
925 done
926 fi
927
928 }
929
930 #---------------------------------------------------------------------
931 ## Passthrough to real_generic_optional_depends, specifies the
932 ## parts that differ from suggest depends
933 #---------------------------------------------------------------------
934 function real_optional_depends() {
935 real_generic_optional_depends "no" "an" "optional dependency" "optional" "$@"
936 }
937
938 #---------------------------------------------------------------------
939 ## Passthrough to real_generic_required_depends, specifies the
940 ## parts that differ from optional depends
941 #---------------------------------------------------------------------
942 function real_suggest_depends() {
943 real_generic_optional_depends "yes" "a" "suggested dependency" "suggest" "$@"
944 }
945
946
947 #---------------------------------------------------------------------
948 ## Asks the user what provider for a depends is desired if a choice
949 ## has not ben made before.
950 ## @param Service
951 ## @param Enabled options
952 ## @param Description
953 #---------------------------------------------------------------------
954 function work_depends_provider()
955 {
956
957 debug "libdepends" "$FUNCNAME - $@"
958 local default tmp installed=no
959 local choices
960 local status=()
961
962 local failure_ok=$1
963 local article=$2
964 local query_term=$3
965 local database_term=$4
966 shift 4
967
968 if [[ $3 ]] ; then
969 depends_message "${SPELL}" "has $article $query_term on some" "${1}" "($3)."
970 else
971 depends_message "$SPELL" "has $article $query_term on some" "${1}."
972 fi
973
974 local CANDIDATES=$( find_providers $1)
975 if [[ ! $CANDIDATES ]] ; then
976 message "${PROBLEM_COLOR}No providers of${DEFAULT_COLOR}" \
977 "${SPELL_COLOR}$1${DEFAULT_COLOR}" \
978 "${PROBLEM_COLOR} can be found!${DEFAULT_COLOR}"
979 if [[ $failure_ok == "no" ]] || ! query "Build $1 anyway?" y; then
980 return 1
981 fi
982 fi
983
984 # if not reconfiguring check if theres already an answer in DEPENDS_STATUS
985 if [[ ! $RECONFIGURE ]]; then
986 # notice the clever ignorance of optional/required depends for the
987 # provider case, if the user chose none, we would fall out during spell_ok
988 # and we transparently switch between optional and required without
989 # anyone noticing
990 explode "$(search_depends_status $DEPENDS_STATUS "$SPELL" ".*($1)")" ":" "status"
991 tmp=${status[1]%(*} # Name of spell which provides $1
992 if spell_ok $tmp; then
993 message "${MESSAGE_COLOR}Using ${SPELL_COLOR}$tmp${DEFAULT_COLOR}"
994 private_common_depends "$tmp($1)" "on" "$database_term" "$2" "$3"
995 return 0
996 fi
997 fi
998
999 # check if theres an abandoned answer, but only if its still a provider
1000 if [[ ! $default ]] && [ -e $ABANDONED_DEPENDS/$SPELL ] ; then
1001 tmp=$(search_depends_status $ABANDONED_DEPENDS/$SPELL "$SPELL" ".*($1)"|awk -F: '{print $2;exit}')
1002 [[ $tmp ]] && real_list_find "$CANDIDATES" "$tmp" && default=$tmp
1003 fi
1004
1005 # check if theres a default provider
1006 if [[ ! $default ]]; then
1007 explode "$(search_default_provider $DEFAULT_PROVIDERS ".*" "$1")" ":" "status"
1008 tmp=${status[0]}
1009 [[ $tmp ]] && real_list_find "$CANDIDATES" "$tmp" && default=$tmp
1010 fi
1011
1012 # check if we've already answered this question
1013 if [[ ! $default ]]; then
1014 for tmp in $CANDIDATES; do
1015 real_list_find "${spells[*]}" "$tmp" && default=$tmp && break
1016 done
1017 fi
1018
1019 # check if theres a provider already installed
1020 # if there are multiple, try to select the previously used one
1021 if [[ ! $default ]]; then
1022 for tmp in $CANDIDATES; do
1023 spell_ok $tmp && real_list_add choices $tmp
1024 done
1025 if [[ $choices == ${choices##* } ]]; then
1026 default=$choices
1027 else
1028 explode "$(search_depends_status $DEPENDS_STATUS "$SPELL" ".*($1)")" ":" "status"
1029 local old_provider=${status[1]%(*} # Name of spell which provides $1
1030 if real_list_find "$choices" $old_provider; then
1031 default=$old_provider
1032 else
1033 default=${choices%% *}
1034 fi
1035 fi
1036 fi
1037
1038 local provider
1039 select_provider "provider" "$default" 0 $CANDIDATES
1040
1041 private_common_depends "$provider($1)" "on" "$database_term" "$2" ""
1042 }
1043
1044 #---------------------------------------------------------------------
1045 ## One of the worker functions. Checks for exiled spell and passes
1046 ## on to the common dependency function, <@function private_common_depends>
1047 ## @param Spell
1048 ## @param enabled options
1049 #---------------------------------------------------------------------
1050 function work_depends_spell()
1051 {
1052 debug "libdepends" "$FUNCNAME - $@"
1053
1054 local failure_ok=$1
1055 local article=$2
1056 local query_term=$3
1057 local database_term=$4
1058 shift 4
1059
1060 depends_message "${SPELL}" "has $article $query_term on" "$1"
1061
1062 if spell_exiled $1 ; then
1063 depends_message "${1}" "has been exiled!"
1064 if [[ $failure_ok == "no" ]] || ! query "Build $1 anyway?" y; then
1065 hash_put $CANNOT_CAST_HASH "$1" "Exiled"
1066 grep -qs $1 $FAILED_LIST || echo $1 >> $FAILED_LIST
1067 log_failure_reason exiled $1
1068 return 1
1069 fi
1070 fi
1071 private_common_depends "$1" "on" "$database_term" "$2" ""
1072
1073 }
1074
1075 #---------------------------------------------------------------------
1076 ## @param provider name
1077 ## @param addition to OPTS if enabled
1078 ## @param addition to OPTS if disabled
1079 ## @param description
1080 ## Handles optional dependency on a provider.
1081 #---------------------------------------------------------------------
1082 function work_optional_depends_provider()
1083 {
1084
1085 debug "libdepends" "$FUNCNAME - $@"
1086 local default tmp choices installed=no
1087 local status=()
1088
1089 local failure_ok=$1
1090 local article=$2
1091 local query_term=$3
1092 local database_term=$4
1093 shift 4
1094
1095 if [[ $4 ]] ; then
1096 depends_message "${SPELL}" "has $article $query_term on some" "${1}" "($4)."
1097 else
1098 depends_message "${SPELL}" "has $article $query_term on some" "${1}."
1099 fi
1100
1101 local CANDIDATES=$( find_providers $1)
1102 # if not reconfiguring check if theres already an answer in DEPENDS_STATUS
1103 if [[ ! $RECONFIGURE ]]; then
1104 explode "$(search_depends_status_simple $DEPENDS_STATUS "$SPELL" ".*($1)" "on")" ":" "status"
1105 local tmp=${status[1]%(*} # Name of spell which provides $1
1106 if [[ "$tmp" ]] && spell_ok "$tmp"; then
1107 message "${MESSAGE_COLOR}Using ${SPELL_COLOR}$tmp${DEFAULT_COLOR}"
1108 private_common_depends "$tmp($1)" "on" "$database_term" "$2" "$3"
1109 return 0
1110 fi
1111 if [[ "$(search_depends_status_simple $DEPENDS_STATUS \
1112 "$SPELL" ".*($1)" "off")" ]]; then
1113 message "${MESSAGE_COLOR}Using ${SPELL_COLOR}[none]${DEFAULT_COLOR}"
1114 private_common_depends "$tmp($1)" "off" "$database_term" "$2" "$3"
1115 return 0
1116 fi
1117 fi
1118
1119 # check if theres an abandoned answer, but only if its still a provider
1120 if [[ ! $default ]] && [ -e $ABANDONED_DEPENDS/$SPELL ] ; then
1121 tmp=$(search_depends_status_simple $ABANDONED_DEPENDS/$SPELL "$SPELL" ".*($1)" "on"|awk -F: '{print $2;exit}')
1122 if [[ $tmp ]] && real_list_find "$CANDIDATES" "$tmp"; then
1123 default=$tmp
1124 else
1125 tmp=$(search_depends_status_simple $ABANDONED_DEPENDS/$SPELL "$SPELL" ".*($1)" "off")
1126 [[ $tmp ]] && default=none
1127 fi
1128 fi
1129
1130 # check if theres a default provider
1131 if [[ ! $default ]]; then
1132 tmp=$(search_default_provider $DEFAULT_PROVIDERS ".*" "$1")
1133
1134 # make sure we found /something/ before trying to analyze it
1135 # otherwise we'll fall into the else case and use 'none' as the
1136 # provider, and short-circuit the other guesses
1137 if [[ $tmp ]] ; then
1138 explode "$tmp" ":" "status"
1139 tmp=${status[0]}
1140 if [[ ${status[2]} == on ]] ; then
1141 # if the user said "on" use the default rather than none
1142 # unless theres something wrong with the provider they chose
1143 # in which case fall back to none
1144 if [[ $tmp ]] && real_list_find "$CANDIDATES" "$tmp"; then
1145 default=$tmp
1146 else
1147 message "${PROBLEM_COLOR}The default provider is not good anymore!"
1148 message "Falling back to 'none' as the default choice.$DEFAULT_COLOR"
1149 default=none
1150 fi
1151 else
1152 default=none
1153 fi
1154 fi
1155 fi
1156
1157 # check if we've already answered this question
1158 if [[ ! $default ]]; then
1159 for tmp in $CANDIDATES; do
1160 real_list_find "${spells[*]}" "$tmp" && default=$tmp && break
1161 done
1162 fi
1163
1164 # check if theres a provider already installed
1165 # if there are multiple, try to select the previously used one
1166 if [[ ! $default ]]; then
1167 for tmp in $CANDIDATES; do
1168 spell_ok $tmp && real_list_add choices $tmp
1169 done
1170 if [[ $choices == ${choices##* } ]]; then
1171 default=$choices
1172 else
1173 # only search for enabled dependencies since none is already the default
1174 explode "$(search_depends_status_simple $DEPENDS_STATUS "$SPELL" ".*($1)" "on")" ":" "status"
1175 local old_provider=${status[1]%(*} # Name of spell which provides $1
1176 if real_list_find "$choices" $old_provider; then
1177 default=$old_provider
1178 else
1179 default=${choices%% *}
1180 fi
1181 fi
1182 fi
1183
1184 local provider
1185 select_provider "provider" "$default" 1 $CANDIDATES
1186
1187 if [ $provider == "none" ] ; then
1188 private_common_depends "($1)" "off" "$database_term" "$2" "$3"
1189 else
1190 private_common_depends "$provider($1)" "on" "$database_term" "$2" "$3"
1191 fi
1192
1193 }
1194
1195 #---------------------------------------------------------------------
1196 ## @param spell
1197 ## @param question
1198 ## @param default answer
1199 ##
1200 ## @return 0 on yes
1201 ## @return 1 on no
1202 ##
1203 ## Works just like normal query but can show short description of a
1204 ## spell and stops the timer for taking the default answer if
1205 ## h/H is pressed. Type of query is chosen in sorcery feature menu.
1206 ##
1207 #---------------------------------------------------------------------
1208 function optional_depends_query() {
1209 local _response
1210 local spell_name=$1
1211 local time_to_answer=$PROMPT_DELAY
1212
1213 while true; do
1214 _response=""
1215
1216 if [[ -z $SILENT ]]; then
1217 if [[ $SHOW_GAZE_SHORT_QUERY == off ]]; then
1218 echo -e -n "${QUERY_COLOR}$2 [$3] ${DEFAULT_COLOR}"
1219 else
1220 if [[ $3 == y ]]; then
1221 echo -e -n "${QUERY_COLOR}$2 [Y/n/h] ${DEFAULT_COLOR}"
1222 else
1223 echo -e -n "${QUERY_COLOR}$2 [y/N/h] ${DEFAULT_COLOR}"
1224 fi
1225 fi
1226
1227 if [[ -n $time_to_answer ]]; then
1228 read -t $time_to_answer -n 1 _response
1229 echo
1230 else
1231 read -n 1 _response
1232 echo
1233 fi
1234 fi
1235
1236 _response=${_response:=$3}
1237 case $_response in
1238 n|N) return 1 ;;
1239 y|Y) return 0 ;;
1240 h|H) ( codex_set_current_spell_by_name $spell_name
1241 echo $SHORT
1242 echo More information at: $WEB_SITE
1243 )
1244 unset time_to_answer
1245 esac
1246 done
1247 }
1248
1249 #---------------------------------------------------------------------
1250 ## @param spell name
1251 ## @param addition to OPTS if enabled
1252 ## @param addition to OPTS if disabled
1253 ## @param description
1254 ## Handles optional dependency on a spell.
1255 #---------------------------------------------------------------------
1256 function work_optional_depends_spell()
1257 {
1258
1259 debug "libdepends" "$FUNCNAME - $@"
1260 local default
1261
1262 local failure_ok=$1
1263 local article=$2
1264 local query_term=$3
1265 local database_term=$4
1266 shift 4
1267
1268 # if $1 optionally depends on something exiled we always say no
1269 if spell_exiled $1 ; then
1270 depends_message "${1}" "has been exiled! not using as $article $query_term"
1271 # don't put it into the bad_spells hash, since it wasn't specified directly
1272 #hash_put $CANNOT_CAST_HASH "$1" "Exiled"
1273 private_common_depends "$1" "off" "$database_term" "$2" "$3"
1274 return 0
1275 fi
1276
1277
1278 if [[ ! $RECONFIGURE ]] ; then
1279 # See if there are preferences already in DEPENDS_STATUS, but only if
1280 # not reconfiguring...
1281 # example: icewm:imlib:off:optional:--with-imlib:--with-xpm
1282 local status=()
1283 explode "$(search_depends_status $DEPENDS_STATUS "$SPELL" "$1")" ":" "status"
1284 if [[ ${status[2]} ]] ; then
1285 # ah there are! use them
1286 if [[ ${status[2]} == "on" ]] ; then
1287 depends_message "${SPELL}" "has an enabled $query_term on" "${1}"
1288 else
1289 depends_message "${SPELL}" "has a disabled $query_term on" "${1}"
1290 fi
1291 private_common_depends "$1" "${status[2]}" "$database_term" "$2" "$3"
1292 return 0
1293 fi
1294 fi
1295 # colors differ from depends_message
1296 if [[ $4 ]]; then
1297 message "${SPELL_COLOR}${SPELL}${DEFAULT_COLOR}" \
1298 "has $article $query_term on" \
1299 "${SPELL_COLOR}$1${DEFAULT_COLOR} ($4)"
1300 else
1301 message "${SPELL_COLOR}${SPELL}${DEFAULT_COLOR}" \
1302 "has $article $query_term on" \
1303 "${SPELL_COLOR}$1${DEFAULT_COLOR}"
1304 fi
1305
1306
1307 # check for abandoned answers
1308 if [ -e $ABANDONED_DEPENDS/$SPELL ] ; then
1309 debug "libdepends" "Checking in abandoned depends"
1310 default=$(search_depends_status $ABANDONED_DEPENDS/$SPELL "$SPELL" "$1"|awk -F: '{print $3;exit}')
1311 fi
1312
1313 # check the defaults file...
1314 # first for explicit $SPELL -> $2
1315 if [[ ! $default ]]; then
1316 debug "libdepends" "Checking in default answers"
1317 default=$(search_default_depends $DEFAULT_DEPENDS $SPELL $1|awk -F: '{print $3; exit}')
1318 fi
1319
1320 # then for anything -> $2
1321 if [[ ! $default ]]; then
1322 debug "libdepends" "Checking in default answers"
1323 default=$(search_default_depends $DEFAULT_DEPENDS "" $1|awk -F: '{print $3; exit}')
1324 fi
1325
1326 # then for $1 -> anything
1327 if [[ ! $default ]]; then
1328 debug "libdepends" "Checking in default answers"
1329 default=$(search_default_depends $DEFAULT_DEPENDS $SPELL "" |awk -F: '{print $3; exit}')
1330 fi
1331
1332 # check the install queue
1333 if [[ ! $default ]]; then
1334 debug "libdepends" "Checking in queue"
1335 real_list_find "${spells[*]}" "$1" && default=on
1336 fi
1337
1338 # check if installed/held
1339 if [[ ! $default ]]; then
1340 debug "libdepends" "Checking if already installed"
1341 spell_ok $1 && default=on
1342 fi
1343
1344 # otherwise default to no
1345 [[ ! $default ]] && default=off
1346
1347 local install=off
1348
1349 local stuff
1350 [[ $default == off ]] && stuff=n || stuff=y
1351
1352 if spell_ok $1 ; then
1353 optional_depends_query "$1" "Do you want to use ${SPELL_COLOR}$1${QUERY_COLOR}?" "$stuff" &&
1354 install="on"
1355 else
1356 optional_depends_query "$1" "Do you want to cast ${SPELL_COLOR}$1${QUERY_COLOR}?" "$stuff" &&
1357 install="on"
1358 fi
1359
1360 private_common_depends "$1" "$install" "$database_term" "$2" "$3"
1361 }
1362
1363 #---------------------------------------------------------------------
1364 ## @param name of return variable
1365 ## @param default answer
1366 ## @param 0 if required 1 if optional
1367 ## @param list of possible providers
1368 ## Present a list to the user complete with info about whats installed
1369 ## and what isnt and allow a default value to be used
1370 #---------------------------------------------------------------------
1371 function select_provider()
1372 {
1373 local returnvar=$1
1374 local default=$2
1375 local optional=$3
1376 local i
1377 shift 3
1378
1379 local each default_char=0 stuff=()
1380 local char
1381
1382 # we can only read one character so use every one we can, I dont expect
1383 # there to be more than 62 providers
1384
1385 # in bash 3.0 this expands to all the numbers and letters
1386 # stuff=({0..9} {a..z} {A..Z})
1387 # but we're still on bash 2 which cant do that, if someone
1388 # knows a better way to do this please tell me
1389 stuff=(0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z)
1390
1391 if [ $optional == 1 ] ; then
1392 hash_put CHAR_TO_SPELL 0 "none"
1393 let i=1
1394 message "\t${DEFAULT_COLOR}(0)\t${SPELL_COLOR}[none]${DEFAULT_COLOR}"
1395 else
1396 let i=0
1397 fi
1398
1399 for each in $@; do
1400 char=${stuff[$i]}
1401 hash_put CHAR_TO_SPELL $char $each
1402
1403 [[ $each == $default ]] && default_char=$char
1404 if spell_ok $each ; then
1405 message "\t${DEFAULT_COLOR}($char)\t${SPELL_COLOR}$each${DEFAULT_COLOR}\t (installed)"
1406 else
1407 message "\t${DEFAULT_COLOR}($char)\t${SPELL_COLOR}$each${DEFAULT_COLOR}"
1408 fi
1409 let i++
1410 done
1411
1412 local msg="\n${QUERY_COLOR}Which one do you want? [$default_char]$DEFAULT_COLOR "
1413 select_list_sub "$returnvar" CHAR_TO_SPELL "$msg" "$default_char"
1414 hash_unset CHAR_TO_SPELL
1415 }
1416
1417 #---------------------------------------------------------------------
1418 ## @param Target of the trigger
1419 ## @param Action to execute (cast_self, check_self, etc).
1420 ##
1421 ## Create a trigger on ourself effecting the target spell,
1422 ## shorthand for putting a TRIGGERS file in the target spell.
1423 #---------------------------------------------------------------------
1424 function real_up_trigger() {
1425 message "${SPELL_COLOR}${SPELL}${DEFAULT_COLOR}" \
1426 "${CHECK_COLOR}triggers a${DEFAULT_COLOR}" \
1427 "${SPELL_COLOR}${2}${DEFAULT_COLOR}" \
1428 "${CHECK_COLOR}on${DEFAULT_COLOR}" \
1429 "${SPELL_COLOR}${1}${DEFAULT_COLOR}"
1430 private_up_trigger $SPELL "$1" "$2"
1431 }
1432
1433 #---------------------------------------------------------------------
1434 ## @param Current spell
1435 ## @param Target target of the trigger
1436 ## @param Action to execute (cast_self, check_self, etc).
1437 ##
1438 ## Register a trigger, when $SPELL is cast, a $ACTION is executed
1439 ## on $TARGET
1440 #---------------------------------------------------------------------
1441 function private_up_trigger() {
1442 local SPELL=$1
1443 local TARGET=$2
1444 local ACTION=$3
1445 # this maps triggerers to their trigerees
1446 # perl -> cast_self:perl_module
1447 hash_append trg_f_hash $SPELL "$TARGET:$ACTION" $'\n' &&
1448 # this maps trigerees to triggerers
1449 # cast_self:perl_module -> perl
1450 hash_append trg_r_hash "$TARGET:$ACTION" " $SPELL "
1451
1452 # afk 6-7-06 Im not sure this line is correct, it seems to only
1453 # make a circular depends, instead we want $TARGET to depend on $SPELL
1454 real_list_find "${NEW_DEPENDS[*]}" "$TARGET" ||
1455 NEW_DEPENDS=( ${NEW_DEPENDS[*]} $spell)
1456
1457 triggerees=( ${triggerees[*]} $TARGET )
1458 }
1459
1460 #---------------------------------------------------------------------
1461 ## @param spell providing the sub-depends
1462 ## @param name of sub-depends
1463 ##
1464 ## Request a sub-depends from $SPELL on $1 for $2
1465 ## This queues the sub-depends for later processing, if the sub-dependee
1466 ## does not already support the sub-depends.
1467 #---------------------------------------------------------------------
1468 function real_sub_depends() {
1469 $STD_DEBUG
1470 local requester=$SPELL
1471 local sub_dependee=$1
1472 local sub_depends=$2
1473
1474 message "${SPELL_COLOR}${SPELL}${MESSAGE_COLOR} requests" \
1475 "${SPELL_COLOR}$sub_dependee${DEFAULT_COLOR}" \
1476 "${CHECK_COLOR}with ${SPELL_COLOR}$sub_depends${DEFAULT_COLOR}"
1477
1478 # Check if the sub-depends is already known
1479 if spell_ok $sub_dependee; then
1480 if [[ $(search_sub_depends "$SUB_DEPENDS_STATUS" "$requester" \
1481 "$sub_dependee" "$sub_depends") != "" ]]; then
1482 debug "libdepends" "$FUNCNAME -- $requester -> $sub_dependee" \
1483 "-> $sub_depends provided by installed spell"
1484 return 0
1485 fi
1486
1487 # the spell is installed, but the sub-depends isn't recorded, ask the
1488 # spell if the sub-depends is enabled through the PRE_SUB_DEPENDS file.
1489 (
1490 THIS_SUB_DEPENDS=$sub_depends
1491 if ! tablet_set_spell $sub_dependee ; then
1492 codex_set_current_spell_by_name $sub_dependee || return 1
1493 fi
1494 run_spell_file PRE_SUB_DEPENDS pre_sub_depends
1495 rc=$?
1496 return $rc
1497 ) && {
1498 debug "libdepends" "adding altruistic sub-depends for $sub_dependee with $sub_depends from $requester"
1499 add_sub_depends "$SUB_DEPENDS_STATUS" "$requester" \
1500 "$sub_dependee" "$sub_depends"
1501 hash_append sub_dep_f_hash $requester $sub_dependee:$sub_depends $'\n'
1502 hash_append sub_dep_r_hash $sub_dependee $requester:$sub_depends $'\n'
1503 return 0
1504 }
1505 fi
1506
1507 # if didnt return above, then we know the sub-depends is not on the system
1508 # so the spell must be (re)cast, check to see if we're allowed to do that
1509 if ! real_list_find "$PRETEND_NOT_INSTALLED" $sub_dependee &&
1510 spell_held $sub_dependee; then
1511 # spell is held and not explicitly requested, so we cant recast the
1512 # spell with the sub-depends requested
1513 message "${PROBLEM_COLOR}Sub-depends requested on" \
1514 "a held spell: $SPELL_COLOR$sub_dependee$DEFAULT_COLOR"
1515 return 1
1516 fi
1517
1518 # add to hashes for lookup later in depends resolution
1519 hash_append sub_dep_f_hash $requester $sub_dependee:$sub_depends $'\n'
1520 hash_append sub_dep_r_hash $sub_dependee $requester:$sub_depends $'\n'
1521
1522 # spell is either not installed, or is installed but without the
1523 # sub-depends, we must (re)cast it
1524 NEW_SUB_DEPENDEES=( ${NEW_SUB_DEPENDEES[*]} $sub_dependee )
1525 hash_put sub_depends_process $sub_dependee "yes"
1526 return 0
1527 }
1528
1529 #---------------------------------------------------------------------
1530 ## Force a spell to be recast, if it comes up for processing
1531 ## if the spell was already looked at and processed nothing happens
1532 ## if the spell was already looked at and didnt need processing, then
1533 ## it'll get re-processed (assuming the caller also did a depends on it)
1534 #---------------------------------------------------------------------
1535 function real_force_depends() {
1536 debug "libdepends" "$FUNCNAME - $SPELL - $@"
1537 local check
1538 hash_get_ref "depends_looked_at" "$1" check
1539
1540 message "${SPELL}" "is forcing a recast of" "${1}"
1541
1542 if [[ "$check" == "ignore" ]] ; then
1543 hash_put "depends_looked_at" "$1" ""
1544 fi
1545 FORCE_DEPENDS=( ${FORCE_DEPENDS[*]} $1 )
1546 }
1547
1548 #---------------------------------------------------------------------
1549 ## all the depends callbacks eventually bottom out here
1550 ## if a spell depends or doesnt depend on some other spell
1551 ## @param Spell
1552 ## @param on/off
1553 #---------------------------------------------------------------------
1554 function private_common_depends()
1555 {
1556 debug "libdepends" "$FUNCNAME - $SPELL - $@"
1557 add_depends $spell_depends "$SPELL" "$@"
1558
1559 # runtime and suggested depends have no formal dependency info
1560 if [[ $2 == on ]] ; then
1561 # ${1%(*} = spell name (strips potential provider name)
1562 local spell_name=${1%(*}
1563 case $3 in
1564 runtime|suggest)
1565 NEW_RUNTIME_DEPENDS=( ${NEW_RUNTIME_DEPENDS[*]} $spell_name ) ;;
1566 *) NEW_DEPENDS=( ${NEW_DEPENDS[*]} $spell_name ) ;;
1567 esac
1568 fi
1569
1570
1571 return 0
1572 }
1573
1574 #---------------------------------------------------------------------
1575 ## Default trigger checking function. Asks user if they want to
1576 ## run the trigger.
1577 #---------------------------------------------------------------------
1578 function real_default_sorcery_trigger_check() {
1579 message "${SPELL_COLOR}${SPELL}${DEFAULT_COLOR}" \
1580 "${CHECK_COLOR}triggers a" \
1581 "${SPELL_COLOR}${ACTION}${DEFAULT_COLOR}" \
1582 "${CHECK_COLOR}on${DEFAULT_COLOR}" \
1583 "${SPELL_COLOR}${TARGET}${DEFAULT_COLOR}"
1584 query "Run the trigger?" y
1585 }
1586
1587 #---------------------------------------------------------------------
1588 ## Inspects each trigger, asks the user if they want to run it.
1589 #---------------------------------------------------------------------
1590 function private_add_triggerees() {
1591
1592 # add the spells that we trigger to the $spells list
1593 # having duplicate items is okay
1594 local ACTION TARGET
1595 local running_trigger
1596
1597 # run the trigger check file
1598 # this is made into a sub-function just to reduce duplication...
1599 function private_add_triggerees_sub1() {
1600 run_spell_file TRIGGER_CHECK trigger_check
1601 running_trigger=$?
1602 if [[ $running_trigger == 0 ]] ; then
1603 private_up_trigger "$SPELL" "$TARGET" "$ACTION"
1604 fi
1605 }
1606
1607 # frontend to help">help">help with calling the trigger check file
1608 function private_add_triggerees_sub2() {
1609 local ACTION=$1
1610 private_add_triggerees_sub1
1611 }
1612
1613 for ACTION in cast_self check_self dispel_self run_script; do
1614 for TARGET in $(get_triggerees $SPELL on_cast $ACTION); do
1615 spell_ok $TARGET || continue
1616 if [[ $ACTION == run_script ]] ; then
1617 iterate private_add_triggerees_sub2 $'\n' \
1618 "$(get_run_script_triggers $SPELL on_cast $TARGET)"
1619 else
1620 private_add_triggerees_sub1
1621 fi
1622 done
1623 done
1624 return 0
1625 }
1626
1627
1628 #---------------------------------------------------------------------
1629 ## Adds the dependency to the hastable
1630 #---------------------------------------------------------------------
1631 function private_add_depends()
1632 {
1633 debug "libdepends" "$FUNCNAME: SPELL=$SPELL, NEW_DEPENDS=${NEW_DEPENDS[*]}"
1634 hash_append "$CAST_HASH" "$SPELL" "${NEW_DEPENDS[*]}"
1635
1636 for child in ${NEW_DEPENDS[*]}; do
1637 hash_append "$BACK_CAST_HASH" "$child" "$SPELL"
1638 done
1639
1640 # force implied basesystem dependency in the depends tree
1641 if [[ $FORCE_BASESYSTEM_DEPENDS == on ]] &&
1642 [[ $SPELL != basesystem ]] &&
1643 ! real_list_find "$base_deps" "$SPELL"; then
1644 hash_append "$CAST_HASH" "$SPELL" "basesystem"
1645 hash_append "$BACK_CAST_HASH" "basesystem" "$SPELL"
1646 fi
1647
1648 spells=( ${spells[*]} ${NEW_DEPENDS[*]}
1649 ${NEW_SUB_DEPENDEES[*]}
1650 ${NEW_RUNTIME_DEPENDS[*]} )
1651
1652 RUNTIME_DEPENDS=( ${RUNTIME_DEPENDS[*]} ${NEW_RUNTIME_DEPENDS[*]} )
1653
1654 TRIGGEREES=( ${TRIGGEREES[*]} ${triggerees[*]} )
1655 spells=( ${spells[*]} ${triggerees[*]} )
1656
1657 UP_DEPENDS=( ${UP_DEPENDS[*]} ${NEW_UP_DEPENDS[*]} )
1658
1659 hash_put "depends_looked_at" "$SPELL" "done"
1660
1661 }
1662
1663 #---------------------------------------------------------------------
1664 ## Determine if spell should be lazily updated, possible asks the user
1665 ## what to do.
1666 #---------------------------------------------------------------------
1667 function want_lazy_update() {
1668 if [[ $LAZY_DEPENDS_UPDATES ]] && [[ $LAZY_DEPENDS_UPDATES != ignore ]] ; then
1669 if does_spell_need_update "$1" ; then
1670 depends_message "$1" "needs updating"
1671 if [[ "$LAZY_DEPENDS_UPDATES" == always ]] ; then
1672 return 0
1673 else
1674 default=n
1675 [[ $LAZY_DEPENDS_UPDATES == ask-yes ]] && default=y
1676 query "Would you like to update it?" $default && return 0 || return 1
1677 fi
1678 fi
1679 fi
1680 return 1
1681 }
1682
1683 function depends_message() {
1684 if [[ $# -ge 2 ]] ; then
1685 message -n "${SPELL_COLOR}${1}${DEFAULT_COLOR}" \
1686 "${CHECK_COLOR}${2}${DEFAULT_COLOR}"
1687 fi
1688 if [[ $# -ge 3 ]] ; then
1689 message -n " ${SPELL_COLOR}${3}${DEFAULT_COLOR}"
1690 fi
1691 if [[ $# -ge 4 ]] ; then
1692 message -n " $4"
1693 fi
1694 message ""
1695 }
1696
1697 #########################BEGIN OTHER STUFF############################
1698
1699 #---------------------------------------------------------------------
1700 ## @param Spell name
1701 ## Removes a dependency and its dependees from the to_cast list.
1702 #---------------------------------------------------------------------
1703 function private_remove_dependees()
1704 {
1705 local spell=$1
1706 local removed_list dependee dependees
1707 message "${PROBLEM_COLOR}Removing dependees of $SPELL_COLOR$spell$DEFAULT_COLOR"
1708
1709 # take care of the spell
1710 private_discard_spell $spell fail
1711
1712 # take care of the dependees and their dependees and ...
1713 recurse_remove_dependees() {
1714 local spell=$1
1715 local dependees dependee
1716 while uncommitted_upward_depends $spell dependees; do
1717 [[ -z $dependees ]] && break
1718 for dependee in $dependees; do
1719 private_discard_spell $dependee
1720 real_list_add removed_list $dependee
1721 recurse_remove_dependees $dependee
1722 done
1723 done
1724 }
1725
1726 recurse_remove_dependees $spell
1727
1728 # take care of dependencies of removed dependees
1729 # but don't remove them if they were specified manually or
1730 # if they wouldn't be cast at all or
1731 # if something else needs them
1732 recurse_remove_dependencies() {
1733 local spell=$1
1734 local dependency dependees ignore dependees2
1735 # use BACK_CAST_HASH since we've already cleared CAST_HASH
1736 # it is in the form of dependency : dependee1 dependee2 ...
1737 for dependency in $(hash_get_table_fields $BACK_CAST_HASH); do
1738 hash_get_ref $BACK_CAST_HASH $dependency dependees
1739 if real_list_find "$dependees" $spell &&
1740 hash_get_ref "depends_looked_at" "$dependency" ignore &&
1741 [[ $ignore != ignore ]] &&
1742 uncommitted_upward_depends $dependency dependees2 &&
1743 [[ -z $dependees2 ]] &&
1744 ! real_list_find "$SPELLS" $dependency; then
1745 hash_unset_part $BACK_CAST_HASH $dependency $spell
1746 private_discard_spell $dependency
1747 recurse_remove_dependencies $dependency
1748 fi
1749 done
1750 }
1751
1752 for dependee in $removed_list; do
1753 recurse_remove_dependencies $dependee
1754 done
1755 }
1756
1757 #---------------------------------------------------------------------
1758 ## @param Spell name
1759 ## Does the actual removal
1760 #---------------------------------------------------------------------
1761 function private_discard_spell()
1762 {
1763 local spell=$1
1764 local failed=$2
1765
1766 grep -qs $spell $FAILED_LIST && return 0
1767
1768 if [[ $failed == fail ]]; then
1769 # spell is being removed from cast list, add to FAILED_LIST
1770 # the rest we want to just show up as dropped
1771 echo "$spell" >> $FAILED_LIST
1772 fi
1773 hash_put depends_looked_at $spell failed
1774 hash_unset "$CAST_HASH" "$spell"
1775 hash_put $CANNOT_CAST_HASH "$spell" "Failed"
1776
1777 local bonus=${BONUS_SPELLS[@]}
1778 local up_depends=${UP_DEPENDS[@]}
1779 if real_list_find "$bonus" $spell; then
1780 real_list_remove bonus $spell
1781 BONUS_SPELLS=( $bonus )
1782 fi
1783 if real_list_find "$up_depends" $spell; then
1784 real_list_remove up_depends $spell
1785 UP_DEPENDS=( $up_depends )
1786 fi
1787 }
1788
1789 #---------------------------------------------------------------------
1790 ## @param Spell name
1791 ## @param Return variable
1792 ## Find all the spells already processed that depend on the spell given as $1
1793 ## Unlike private_upward_depends, this one works with the uncommitted info
1794 #---------------------------------------------------------------------
1795 function uncommitted_upward_depends() {
1796 local _spell=$1
1797 local _upvar=$2
1798 local candidate _dependees _deps
1799
1800 for candidate in $(hash_get_table_fields $CAST_HASH); do
1801 hash_get_ref $CAST_HASH $candidate _deps
1802 if real_list_find "$_deps" $_spell; then
1803 real_list_add _dependees $candidate
1804 fi
1805 done
1806
1807 if [[ -n $_upvar ]]; then
1808 upvar $_upvar $_dependees
1809 else
1810 echo $_dependees
1811 fi
1812 }
1813
1814 #---------------------------------------------------------------------
1815 ## Sets a spell's aux. config info.
1816 ## @Globals SPELL
1817 #---------------------------------------------------------------------
1818 function run_spell_config()
1819 {
1820
1821 SPELL_CONFIG=$DEPENDS_CONFIG/$SPELL
1822 debug "libdepends" "run_spell_config() - DEPENDS_CONFIG=$DEPENDS_CONFIG SPELL=$SPELL, SPELL_CONFIG=$SPELL_CONFIG DEPENDS_STATUS=$DEPENDS_STATUS"
1823
1824 if [ -x $SPELL_CONFIG ]; then
1825 debug "libdepends" "run_spell_config() - found $SPELL_CONFIG"
1826 . $SPELL_CONFIG
1827 fi
1828 }
1829
1830 #---------------------------------------------------------------------
1831 ## Output the upward dependencies of the specified spell
1832 ## @Param spell
1833 ## @Param depth (optional)
1834 ## @Param fast -- if set only show spells, not full depends db entries
1835 ## @Param all - if set returns also runtime dependencies
1836 #---------------------------------------------------------------------
1837 function real_show_up_depends()
1838 {
1839 local i=0
1840 local MAX_DEPTH=$2
1841 local type=$3
1842 local all=$4
1843 function show_up_depends_sub() {
1844 local each dependencies checked
1845 let i++
1846 [[ $MAX_DEPTH ]] && [[ $i -gt $MAX_DEPTH ]] && return
1847 hash_get_ref foo $1 dependencies
1848 for each in $dependencies; do
1849 hash_get_ref done $each checked
1850 if ! [[ $checked ]] ; then
1851 hash_put done $each done
1852 echo $each:$1
1853 show_up_depends_sub $each
1854 elif [[ "$type" == "verbose" ]] ; then
1855 echo $each:$1
1856 fi
1857 done
1858 }
1859 hash_reset foo
1860 hash_reset done
1861 compute_reverse_installed_depends foo $all
1862 if [[ "$type" == "verbose" ]] ; then
1863 lock_file "$DEPENDS_STATUS"
1864 show_up_depends_sub "$1"|while read line; do
1865 grep -e "$line:" -e "$line([^)(]*):" "$DEPENDS_STATUS"
1866 done
1867 unlock_file "$DEPENDS_STATUS"
1868 else
1869 show_up_depends_sub "$1"|cut -f1 -d:
1870 fi|sort -u
1871 hash_reset foo
1872 hash_reset done
1873 }
1874
1875
1876 #---------------------------------------------------------------------
1877 ##=back
1878 ##
1879 ##=head1 LICENSE
1880 ##
1881 ## This software is free software; you can redistribute it and/or modify
1882 ## it under the terms of the GNU General Public License as published by
1883 ## the Free Software Foundation; either version 2 of the License, or
1884 ## (at your option) any later version.
1885 ##
1886 ## This software is distributed in the hope that it will be useful,
1887 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
1888 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1889 ## GNU General Public License for more details.
1890 ##
1891 ## You should have received a copy of the GNU General Public License
1892 ## along with this software; if not, write to the Free Software
1893 ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1894 ##
1895 #---------------------------------------------------------------------