OSDN Git Service

[BUG FIX] Packages for which the flavor mechanism is newly introduced sometimes had...
[portsreinstall/current.git] / lib / libdatabase_build.sh
1 #!/bin/sh -e
2 # ==============================================================================
3 # portsreinstall library script
4 # - Operations for building the temporary database -
5 # Copyright (C) 2013-2022 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
6 # This software is distributed under the 2-Clause BSD License.
7 # ==============================================================================
8
9 # ============= Register an obsolete flavored origin =============
10 database_build_register_obsolete_port ()
11 {
12         local origin dbpath pkgtag
13         origin=$1
14         dbpath=${DBDIR}/obsolete/$origin
15         [ -e "$dbpath/complete_as_node" ] && return
16         mkdir -p "${DBDIR}/obsolete/$origin"
17         pkgtag=`pkgsys_get_init_pkg_from_orig "$origin"`
18         [ -n "$pkgtag" ] || pkgtag='[not installed]'
19         echo "$pkgtag" > ${DBDIR}/obsolete/$origin/pkgtag
20         for table in dependents requirements
21         do
22                 for level in direct full
23                 do
24                         for tag in all run build
25                         do
26                                 srcfile=${DBDIR}/initial/$origin/${table}.${tag}.${level}
27                                 [ -e "$srcfile" ] && ln -f "$srcfile" "$dbpath/${table}.${tag}.${level}.src"
28                         done
29                 done
30         done
31         touch "$dbpath/complete_as_node"
32 }
33
34 # ============= Convert and register if a flavored origin is obsolete =============
35 database_build_convert_and_register_origin_if_obsolete ()
36 {
37         local origin recursedb_in recursedb output_origin iline_db origin_new date_moved why_moved
38         origin=$1
39         recursedb_in=$2
40         recursedb=${recursedb_in:-${PORTS_MOVED_DB}}
41         echo "$origin" > ${TMPDIR}/database_build_convert_and_register_origin_if_obsolete:origin
42         pkgsys_exists_port "$origin" && return
43         database_build_register_obsolete_port "$origin"
44         env LANG=C grep -n -m 1 -E "^`str_escape_regexp \"$origin\"`\|" "$recursedb" 2> /dev/null > ${TMPDIR}/moved.info || :
45         if [ `wc -l < ${TMPDIR}/moved.info` -eq 0 ]
46         then
47                 fileedit_add_a_line_if_new "$origin" "${DBDIR}/obsolete_ports"
48                 fileedit_rm_a_line "$origin" "${DBDIR}/moved_ports"
49                 if [ -n "$recursedb_in" ]
50                 then
51                         message_echo "${DEPTH_INDEX}  ===> Disappeared port (MOVED broken?)"
52                 else
53                         message_echo "${DEPTH_INDEX}  ===> Nonexistent port (your original?)"
54                 fi
55                 return 1
56         else
57                 iline_db=`cut -d : -f 1 "${TMPDIR}/moved.info"`
58                 sed 1,${iline_db}d "${PORTS_MOVED_DB}" > ${TMPDIR}/MOVED.DB
59                 origin_new=`sed -E 's/^[0-9]+://' "${TMPDIR}/moved.info" | cut -d '|' -f 2 || :`
60                 date_moved=`cut -d '|' -f 3 "${TMPDIR}/moved.info" || :`
61                 why_moved=`cut -d '|' -f 4 "${TMPDIR}/moved.info" || :`
62                 if [ -n "$origin_new" ]
63                 then
64                         message_echo "${DEPTH_INDEX}  ===> Moved to $origin_new at $date_moved because \"$why_moved\""
65                         fileedit_add_a_line_if_new "$origin" "${TMPDIR}/database_build_convert_and_register_origin_if_obsolete:origins_old"
66                         fileedit_add_a_line_if_new "$origin" "${DBDIR}/moved_ports"
67                         fileedit_rm_a_line "$origin" "${DBDIR}/obsolete_ports"
68                         database_build_convert_and_register_origin_if_obsolete "$origin_new" "${TMPDIR}/MOVED.DB" || return 1
69                 else
70                         message_echo "${DEPTH_INDEX}  ===> Deleted at $date_moved because \"$why_moved\""
71                         fileedit_add_a_line_if_new "$origin" "${DBDIR}/obsolete_ports"
72                         fileedit_rm_a_line "$origin" "${DBDIR}/moved_ports"
73                         return 1
74                 fi
75         fi
76 }
77
78 # ============= [Sub-function] Get the true latest flavored origin =============
79 database_build_convert_and_register_origin_if_obsolete__get_origin ()
80 {
81         cat "${TMPDIR}/database_build_convert_and_register_origin_if_obsolete:origin"
82 }
83
84 # ============= [Sub-function] Reset the all old origins of the tested flavored origin =============
85 database_build_convert_and_register_origin_if_obsolete__reset_origins_old ()
86 {
87         rm -rf "${TMPDIR}/database_build_convert_and_register_origin_if_obsolete:origins_old"
88 }
89
90 # ============= [Sub-function] Save the all old origins of the tested flavored origin =============
91 database_build_convert_and_register_origin_if_obsolete__save_origins_old ()
92 {
93         cat "${TMPDIR}/database_build_convert_and_register_origin_if_obsolete:origins_old" 2> /dev/null
94 }
95
96 # ============= Get the make arguments for building the temporary database =============
97 database_build_setup_make_args ()
98 {
99         local origin
100         origin=$1
101         {
102                 for key in LOCALBASE LINUXBASE PORT_DBDIR PORTSDIR DISTDIR PACKAGES PKGREPOSITORY
103                 do
104                         eval echo $key=\$$key
105                 done
106                 echo 'DISABLE_VULNERABILITIES=yes'
107                 if [ $opt_apply_default_config = yes ]
108                 then
109                         if pkgsys_is_dialog4ports_used
110                         then
111                                 echo 'NO_DIALOG=yes'
112                         else
113                                 echo 'BATCH=yes'
114                         fi
115                 fi
116                 dbdir=${DBDIR}/requires/$origin
117                 [ -d "$dbdir" ] || dbdir=${DBDIR}/conf/each_port/$origin
118                 cat "$dbdir/MARG.conf" 2> /dev/null || :
119                 flavor=`pkgsys_get_flavor_from_origin "$origin"`
120                 [ -z "$flavor" ] || echo "FLAVOR=$flavor"
121         } | tr '\n' ' '
122 }
123
124 # ============= Get the make environment variables for building the temporary database =============
125 database_build_setup_make_envs ()
126 {
127         local origin dbdir
128         origin=$1
129         dbdir=${DBDIR}/requires/$origin
130         [ -d "$dbdir" ] || dbdir=${DBDIR}/conf/each_port/$origin
131         cat "$dbdir/MENV.conf" 2> /dev/null | tr '\n' ' '
132 }
133
134 # ============= Execute make command for building the temporary database =============
135 database_build_make ()
136 {
137         local origin MAKE_ARGS MAKE_ENVS port_path flavor
138         origin=$1
139         shift
140         MAKE_ARGS=`database_build_setup_make_args "$origin"`
141         MAKE_ENVS=`database_build_setup_make_envs "$origin"`
142         port_path=`pkgsys_get_portpath_from_origin "$origin"`
143         fs_fix_unionfs_image_if_hidden "$port_path"
144         env $MAKE_ENVS make -C "$port_path" "$@" $MAKE_ARGS
145 }
146
147 # ============= Set up a temporary database node for the initial state of a port =============
148 database_build_setup_initial_node ()
149 {
150         local origin pkg dbpath
151         origin=$1
152         dbpath=${DBDIR}/initial/$origin
153         [ -e "$dbpath/complete_as_node" ] && return
154         rm -rf "$dbpath"
155         mkdir -p "$dbpath"
156         pkg=`pkgsys_get_installed_pkg_from_origin "$origin"`
157         if [ -n "$pkg" ]
158         then
159                 echo "$pkg" > $dbpath/installed_version
160                 ln -f "$dbpath/installed_version" "$dbpath/pkgtag"
161                 pkg_info_qr "$pkg" | while read requirement
162                 do
163                         origin_requirement=`pkgsys_init_pkg_orig_by_ambiguous_matching "$requirement" || :`
164                         [ -n "$origin_requirement" ] && echo "$origin_requirement"
165                         :
166                 done > $dbpath/requirements.all.full
167                 pkg_info_qR "$pkg" | while read dependent
168                 do
169                         origin_dependent=`pkgsys_init_pkg_orig_by_ambiguous_matching "$dependent" || :`
170                         [ -n "$origin_dependent" ] && echo "$origin_dependent"
171                         :
172                 done > $dbpath/dependents.all.full
173                 for table in dependents requirements
174                 do
175                         for level in direct full
176                         do
177                                 for tag in all run build
178                                 do
179                                         [ "${tag}.${level}" = all.full ] && continue
180                                         ln -f "$dbpath/${table}.all.full" "$dbpath/${table}.${tag}.${level}"
181                                 done
182                         done
183                 done
184         fi
185         if [ `expr "$pkg" : "^${APPNAME}-[0-9].*"` -gt 0 ]
186         then
187                 [ -d "$dbpath" ] && touch "$dbpath/SUPPRESSED_SELF"
188         elif [ `expr "$pkg" : "^pkg-[0-9].*"` -gt 0 ]
189         then
190                 [ -d "$dbpath" ] && touch "$dbpath/SUPPRESSED_PKGNG"
191         fi
192         touch "$dbpath/complete_as_node"
193 }
194
195 # ============= Set up a temporary database node for the replaced/moved information of a port =============
196 database_build_setup_replace_node ()
197 {
198         local origin_orig portoption_before portoption_after origin_trial origin dbpath tmp_msg flavor_orig flavors flavor origin_trial_unflavored origin_unflavored
199         origin_orig=$1
200         portoption_before=$2
201         portoption_after=$3
202         dbpath=${DBDIR}/replace/$origin_orig
203         tmp_msg=${TMPDIR}/database_build_setup_replace_node:meg
204         if [ ! -e "$dbpath/complete_as_node" ]
205         then
206                 rm -rf "$dbpath"
207                 mkdir -p "$dbpath"
208                 origin_trial=$origin_orig
209                 if echo "$origin_orig" | env LANG=C grep -q -Fx -f "${DBDIR}/conf/REPLACE.filter" 2> /dev/null
210                 then
211                         origin_trial=`echo "$origin_orig" | sed -E -f "${DBDIR}/conf/REPLACE.sed_pattern"`
212                         if [ "x$origin_orig" != "x$origin_trial" ]
213                         then
214                                 if [ -n "$origin_trial" ]
215                                 then
216                                         message_echo "${DEPTH_INDEX}  ===> Replaced with $origin_trial by user configuration"
217                                 else
218                                         database_build_register_obsolete_port "$origin_orig"
219                                         message_echo "${DEPTH_INDEX}  ===> Deleted by user configuration"
220                                 fi > $dbpath/message
221                         fi
222                 fi
223                 if [ -n "$origin_trial" ]
224                 then
225                         if database_build_convert_and_register_origin_if_obsolete "$origin_trial" >> $dbpath/message
226                         then
227                                 origin_trial=`database_build_convert_and_register_origin_if_obsolete__get_origin`
228                         else
229                                 if [ "x$origin_trial" != "x$origin_orig" ]
230                                 then
231                                         message_echo "${DEPTH_INDEX}  ===> Going back to the original port $origin_orig"
232                                         if database_build_convert_and_register_origin_if_obsolete "$origin_orig"
233                                         then
234                                                 origin_trial=`database_build_convert_and_register_origin_if_obsolete__get_origin`
235                                         else
236                                                 origin_trial=
237                                         fi
238                                 else
239                                         origin_trial=
240                                 fi >> $dbpath/message
241                         fi
242                 fi
243                 cat "$dbpath/message" 2> /dev/null || :
244                 if [ -n "$origin_trial" ]
245                 then
246                         database_build_make "$origin_trial" showconfig > $portoption_before 2> /dev/null || :
247                         database_build_determine_port_option "$origin_trial"
248                         database_build_make "$origin_trial" showconfig > $portoption_after 2> /dev/null || :
249                         origin=`database_build_determine_flavored_origin "$origin_trial"`
250                         if [ "x$origin_trial" != "x$origin" ]
251                         then
252                                 if [ -n "$origin" ]
253                                 then
254                                         message_echo "${DEPTH_INDEX}  ===> Transferred to $origin"
255                                 else
256                                         fileedit_add_a_line_if_new "$origin" "${DBDIR}/obsolete_ports"
257                                         message_echo "${DEPTH_INDEX}  ===> Lost (Something is wrong!)"
258                                 fi
259                         fi > $tmp_msg
260                         cat "$tmp_msg" >> $dbpath/message
261                 else
262                         origin=
263                 fi
264                 cat "$tmp_msg" 2> /dev/null || :
265                 # If the flavor mechanism is introduced to an initial origin without flavor, apply the default one.
266                 if [ -n "$origin" -a -n "$origin_trial" ]
267                 then
268                         origin_trial_unflavored=`pkgsys_get_unflavored_origin "$origin_trial"`
269                         origin_unflavored=`pkgsys_get_unflavored_origin "$origin"`
270                         flavor_orig=`pkgsys_get_flavor_from_origin "$origin_trial"`
271                         if [ -z "$flavor_orig" -a "$origin_trial_unflavored" = "$origin_unflavored" ]
272                         then
273                                 flavors=`database_build_make "$origin" -V FLAVORS`
274                                 if [ -n "$flavors" ]
275                                 then
276                                         flavor=`expr "$flavors" : '\([^ ]*\).*'` || :
277                                         if [ -n "$flavor" ]
278                                         then
279                                                 database_build_register_obsolete_port "$origin_trial"
280                                                 fileedit_add_a_line_if_new "$origin_trial" "${DBDIR}/moved_ports"
281                                                 fileedit_rm_a_line "$origin_trial" "${DBDIR}/obsolete_ports"
282                                                 origin=`pkgsys_compose_flavored_origin "$origin_trial" "$flavor"`
283                                                 message_echo "${DEPTH_INDEX}  ===> Moved to $origin by renaming with the default flavor"
284                                         fi
285                                 fi
286                         fi > $tmp_msg
287                         cat "$tmp_msg" >> $dbpath/message
288                 fi
289                 [ "x$origin_orig" = "x$origin" ] || echo "$origin" > $dbpath/origin
290                 cat "$tmp_msg" 2> /dev/null || :
291                 touch "$dbpath/complete_as_node"
292         else
293                 cat "$dbpath/message" 2> /dev/null || :
294         fi
295 }
296
297 # ============= Get the inspected level for a port with the current option settings =============
298 database_build_get_inspected_level ()
299 {
300         local origin origin_dependent
301         origin=$1
302         origin_dependent=$2
303         if [ $opt_only_target_scope = no ]
304         then
305                 echo full
306         elif ! pkgsys_exists_or_existed_from_orig "$origin" \
307                 || env LANG=C grep -qFx "$origin" "${DBDIR}/stage.loop_list/ports_to_inspect" 2> /dev/null \
308                 || [ ! -e "${DBDIR}/moved_from/$origin_dependent/installed_version" ] \
309                 || env LANG=C grep -qFx "$origin_dependent" "${DBDIR}/stage.loop_list/ports_to_inspect" 2> /dev/null
310         then
311                 echo direct
312         else
313                 echo node
314         fi
315 }
316
317 # ============= Check whether a port has been inspected in a required level =============
318 database_build_is_port_already_inspected_in_required_level ()
319 {
320         local origin origin_dependent origin_actual inspected_level
321         origin=$1
322         origin_dependent=$2
323         origin_actual=`echo "$origin" | sed -E -f "${DBDIR}/REPLACE.complete_sed_pattern" 2> /dev/null || :`
324         [ -n "$origin_actual" ] || origin_actual=$origin
325         inspected_level=`database_build_get_inspected_level "$origin_actual" "$origin_dependent"`
326         {
327                 cat "${DBDIR}/ports.inspected.${inspected_level}.list" || :
328                 cat "${DBDIR}/moved_ports" || :
329                 cat "${DBDIR}/obsolete_ports" || :
330         }  2> /dev/null | env LANG=C grep -q -Fx "$origin_actual" || return
331         fileedit_rm_a_line "$origin" "${DBDIR}/stage.loop_list/ports_to_inspect.remain"
332         [ "x$origin" = "$origin_actual" ] || \
333                 fileedit_rm_a_line "$origin_actual" "${DBDIR}/stage.loop_list/ports_to_inspect.remain"
334         echo "$origin_actual"
335 }
336
337 # ============= Update the current package name of a port =============
338 database_build_update_pkgname ()
339 {
340         local origin dbdir pkg savefile
341         origin=$1
342         dbdir=${DBDIR}/moved_from/$origin
343         mkdir -p "$dbdir"
344         savefile=$dbdir/current_version
345         pkg=`pkgsys_get_installed_pkg_from_origin "$origin"`
346         if [ -z "$pkg" -a -e "$dbdir/initial_orig" ]
347         then
348                 while read orig_init
349                 do
350                         pkgsys_get_installed_pkg_from_origin "$orig_init"
351                 done < $dbdir/initial_orig
352         elif [ -n "$pkg" ]
353         then
354                 echo "$pkg"
355         fi | sort -u > $savefile
356         cat "$savefile"
357 }
358
359 # ============= Get the current package name of a port =============
360 database_build_get_pkgname ()
361 {
362         local origin savefile
363         origin=$1
364         savefile=${DBDIR}/moved_from/$origin/current_version
365         if [ -e "$savefile" ]
366         then
367                 cat "$savefile"
368         else
369                 database_build_update_pkgname "$origin"
370         fi
371 }
372
373 # ============= Get the new package name of a port =============
374 database_build_get_new_pkgname ()
375 {
376         local origin savefile
377         origin=$1
378         savefile=${DBDIR}/requires/$origin/new_version
379         if [ ! -e "$savefile" ]
380         then
381                 database_build_make "$origin" package-name \
382                         | tr -d '\n' > $savefile
383         fi
384         cat "$savefile"
385 }
386
387 # ============= Get the package list of full-run-time requirements =============
388 database_build_get_full_run_requirement_pkgs ()
389 {
390         local origin srcfile savefile
391         origin=$1
392         srcfile=${DBDIR}/requires/$origin/requirements.run.full
393         savefile=${DBDIR}/requires/$origin/pkg_requirements.run.full
394         if [ ! -e "$srcfile" ]
395         then
396                 rm -f "$savefile"
397         elif [ ! -e "$savefile" -o "$savefile" -ot "$srcfile" ]
398         then
399                 while read origin
400                 do
401                         database_build_get_new_pkgname "$origin"
402                 done < $srcfile | env LANG=C grep -v '^[[:space:]]*$' | sort -u > $savefile
403         fi
404         cat "$savefile" 2> /dev/null || :
405 }
406
407 # ============= Build the original message tag showing the version upgrade =============
408 database_build_create_pkgtag ()
409 {
410         local origin dbdir pkg_init pkg_new pkgtag
411         origin=$1
412         dbdir=${DBDIR}/moved_from/$origin
413         mkdir -p "$dbdir"
414         pkg_init=`database_build_get_pkgname "$origin"`
415         [ -n "$pkg_init" -a ! -e "$dbdir/installed_version" ] && \
416                 echo -n "$pkg_init" > $dbdir/installed_version
417         pkg_new=`database_build_get_new_pkgname "$origin"`
418         pkgtag=$pkg_init
419         [ -n "$pkgtag" ] || pkgtag=$pkg_new
420         if [ -z "$pkgtag" ]
421         then
422                 pkgtag='?'
423         
424         elif [ "x$pkg_init" != "x$pkg_new" ]
425         then
426                 if [ -n "$pkg_init" ]
427                 then
428                         pkgtag="$pkg_init => $pkg_new"
429                 else
430                         pkgtag="[new] $pkg_new"
431                 fi
432         fi
433         echo "$pkgtag" > $dbdir/pkgtag.orig
434         echo "$pkgtag" > $dbdir/pkgtag
435 }
436
437 # ============= Update the message tag showing the version upgrade =============
438 database_build_update_pkgtag ()
439 {
440         local origin dbdir pkg_init pkg_bak pkg_cur detail pkgtag
441         origin=$1
442         dbdir=${DBDIR}/moved_from/$origin
443         mkdir -p "$dbdir"
444         pkg_init=`cat "$dbdir/installed_version" 2> /dev/null | tr '\n' ' ' | sed 's/ *$//'`
445         pkg_bak=`cat "$dbdir/backedup_version" 2> /dev/null | tr '\n' ' ' | sed 's/ *$//'`
446         pkg_cur=`database_build_get_pkgname "$origin" | tr '\n' ' ' | sed 's/ *$//'`
447         detail=
448         if [ "x$pkg_init" != "x$pkg_cur" ]
449         then
450                 if [ -n "$pkg_cur" ]
451                 then
452                         detail=" [currently installed version: $pkg_cur]"
453                 elif [ -n "$pkg_bak" ]
454                 then
455                         detail=" [currently deinstalled, previously installed version: $pkg_bak]"
456                 else
457                         detail=" [currently deinstalled]"
458                 fi
459         fi
460         pkgtag=`cat "$dbdir/pkgtag.orig"`
461         echo "$pkgtag$detail" > $dbdir/pkgtag
462 }
463
464 # ============= Check whether the currently installed package version is the latest =============
465 database_build_is_currentpkg_latest ()
466 {
467         local origin pkg_cur pkg_new
468         origin=$1
469         pkg_cur=`database_build_get_pkgname "$origin" | tr '\n' ' ' | sed 's/ *$//'`
470         pkg_new=`database_build_get_new_pkgname "$origin"`
471         [ "x$pkg_cur" = "x$pkg_new" ]
472 }
473 # ============= Configure the port option to determine the true flavor =============
474 database_build_determine_port_option ()
475 {
476         local origin
477         origin=$1
478         if [ $opt_apply_default_config = yes ]
479         then
480                 if ! pkgsys_is_dialog4ports_used
481                 then
482                         printf '\t\n' | database_build_make "$origin" config-conditional > /dev/null
483                 fi
484         else
485                 database_build_make "$origin" config-conditional
486         fi
487 }
488
489 # ============= Get the true flavor to determine the flavored port origin =============
490 database_build_determine_flavored_origin ()
491 {
492         local origin origin_unflavored flavor_trial origin_trial flavors_ptn flavor
493         origin=$1
494         origin_unflavored=`pkgsys_get_unflavored_origin "$origin"`
495         flavor_trial=`pkgsys_get_flavor_from_origin "$origin"`
496         if [ -n "$flavor_trial" ]
497         then
498                 flavors_ptn="^("`database_build_make "$origin" -V FLAVORS 2> /dev/null | sed -E 's/[[:space:]]+/|/g'`")$"
499                 echo "$flavor_trial" | env LANG=C grep -qE "$flavors_ptn" || flavor_trial=
500         fi
501         origin_trial=`pkgsys_compose_flavored_origin "$origin_unflavored" "$flavor_trial"`
502         flavor=`database_build_make "$origin_trial" -V FLAVOR 2> /dev/null || :`
503         pkgsys_compose_flavored_origin "$origin_unflavored" "$flavor"
504 }
505
506 # ============= Escape of inspection conflict =============
507 database_build_escape_inspect_conflict ()
508 {
509         local origin dbpath
510         origin=$1
511         dbpath=${DBDIR}/requires/$origin
512         if [ -e "$dbpath/CONFLICT.conf" ]
513         then
514                 message_echo "${DEPTH_INDEX}  ===> Escaping inspection conflict..."
515                 pkgsys_eval_ports_glob `cat "$dbpath/CONFLICT.conf"` | database_build_escape "$dbpath/CONFLICT_pkgarc.lst"
516         fi
517 }
518
519 # ============= Escape of conflicts =============
520 # A list of conflict package origins are given by stdin.
521 database_build_escape ()
522 {
523         local backup_list origin_conflict pkg_conflict pkgarc
524         backup_list=$1
525         while read origin_conflict
526         do
527                 pkg_conflict=`pkgsys_get_installed_pkg_from_origin "$origin_conflict"`
528                 [ -n "$pkg_conflict" ] || continue
529                 message_echo "${DEPTH_INDEX}  ===> Escaping $pkg_conflict..."
530                 pkgarc=`pkgsys_create_backup_pkg "$pkg_conflict" "${DBDIR}/backup_packages" 2> /dev/null` || \
531                         message_echo "${DEPTH_INDEX}  ===> (WARNING: Failed to back up)"
532                 pkg_delete_f "$pkg_conflict" > /dev/null 2>&1 || \
533                         message_echo "${DEPTH_INDEX}  ===> (WARNING: Failed to delete)"
534                 [ -n "$pkgarc" ] && printf '%s\t%s\n' "$pkg_conflict" "$pkgarc" >> $backup_list
535         done
536 }
537
538 # ============= Restoration of escaped inspection conflict =============
539 database_build_restore_inspect_conflict ()
540 {
541         local origin dbpath
542         origin=$1
543         dbpath=${DBDIR}/requires/$origin
544         if [ -e "$dbpath/CONFLICT.conf" ]
545         then
546                 message_echo "${DEPTH_INDEX}  ===> Restoring inspection conflict..."
547                 cat "$dbpath/CONFLICT_pkgarc.lst" 2> /dev/null | database_build_restore
548                 rm -f "$dbpath/CONFLICT_pkgarc.lst"
549         fi
550 }
551
552 # ============= Restoration of escaped conflicts =============
553 # The backup list is given by stdin.
554 database_build_restore ()
555 {
556         local pkg_conflict pkgarc
557         while read pkg_conflict pkgarc
558         do
559                 pkg_info_e "$pkg_conflict" && continue
560                 message_echo "${DEPTH_INDEX}  ===> Restoring $pkg_conflict..."
561                 pkg_add_f "$pkgarc" > /dev/null 2>&1 || \
562                         message_echo "${DEPTH_INDEX}  ===> (WARNING: Failed to restore $pkg_conflict)"
563         done
564 }
565
566 # ============= Recursively inspect dependencies of a port and build a node database of the information =============
567 database_build_inspect_dependencies ()
568 {
569         local origin_orig origin_dependent origin_orig_regexp origin_replace origin tag stage level dbpath dbpath_prev origin_id tmp_config origin_dependency DEPTH_INDEX_orig nlines iline dist_subdir_rpl inspected_level inspected_levels_compatible origin_tmp inspected_level_tmp conf_updated tmp_portsdb_work tmp_portopt same_as_prevset dbfile installed_version frompath variable pkg_new
570         origin_orig=$1
571         origin_dependent=$2
572         [ -z "$origin_orig" ] && return
573         if ! origin=`database_build_is_port_already_inspected_in_required_level "$origin_orig" "$origin_dependent"`
574         then
575                 DEPTH_INDEX_orig=${DEPTH_INDEX}
576                 DEPTH_INDEX="${DEPTH_INDEX}--"
577                 message_echo "${DEPTH_INDEX} $origin_orig"
578                 database_build_convert_and_register_origin_if_obsolete__reset_origins_old
579                 origin_id=`echo "$origin_orig" | tr / :`
580                 # Replacement specified by the configuration file, knobs and port options
581                 tmp_config=${TMPDIR}/database_build_inspect_dependencies:config
582                 database_build_setup_replace_node "$origin_orig" "$tmp_config.before" "$tmp_config.after"
583                 if [ -e "${DBDIR}/replace/$origin_orig/origin" ]
584                 then
585                         origin=`cat "${DBDIR}/replace/$origin_orig/origin"`
586                 else
587                         origin=$origin_orig
588                 fi
589                 # Build the database for this port
590                 inspected_level=
591                 inspected_levels_compatible=
592                 if [ -n "$origin" ]
593                 then
594                         frompath=${DBDIR}/moved_from/$origin
595                         mkdir -p "$frompath"
596                         database_build_convert_and_register_origin_if_obsolete__save_origins_old | \
597                                 fileedit_add_lines_if_new "$frompath/old_origs"
598                         # Check the package name initially installed
599                         installed_version=`cat "${DBDIR}/initial/$origin_orig/installed_version" 2> /dev/null || :`
600                         [ -n "$installed_version" ] && fileedit_add_a_line_if_new "$installed_version" "$frompath/installed_version"
601                         [ "x$origin_orig" = "x$origin" ] || fileedit_add_a_line_if_new "$origin_orig" "$frompath/initial_orig"
602                         [ -e "${DBDIR}/initial/$origin_orig/SUPPRESSED_SELF" ] && touch "$frompath/SUPPRESSED_SELF"
603                         [ -e "${DBDIR}/initial/$origin_orig/SUPPRESSED_PKGNG" ] && touch "$frompath/SUPPRESSED_PKGNG"
604                         if ! env LANG=C grep -qFx "$origin" "${DBDIR}/done_required_ports_to_inspect" 2> /dev/null
605                         then
606                                 fileedit_rm_a_line "$origin" "${DBDIR}/obsolete_ports"
607                                 fileedit_rm_a_line "$origin" "${DBDIR}/moved_ports"
608                                 dbpath=${DBDIR}/requires/$origin
609                                 dbpath_prev=${DBDIR}/prevset/requires/$origin
610                                 if [ ! -e "$dbpath/complete_as_node" ] || \
611                                         ! diff "$tmp_config.before" "$tmp_config.after" > /dev/null 2> /dev/null
612                                 then
613                                         # Notify reconfiguration of the port option
614                                         conf_updated=
615                                         if [ -e "$dbpath/complete_as_node" ] || \
616                                                 env LANG=C grep -q -Fx -e "$origin_orig" -e "$origin" "${DBDIR}/to_be_reconf" 2> /dev/null
617                                         then
618                                                 message_echo "${DEPTH_INDEX}  ===> Reconfigured"
619                                                 conf_updated=y
620                                         fi
621                                         # Reset the database
622                                         rm -rf "$dbpath"
623                                         mkdir -p "$dbpath"
624                                         [ -n "$conf_updated" ] && touch "$dbpath/conf_updated"
625                                         if [ -d "${DBDIR}/conf/each_port/$origin" ]
626                                         then
627                                                 cp -R "${DBDIR}/conf/each_port/$origin/"* "$dbpath/" > /dev/null 2>&1 || :
628                                         fi
629                                         # Escape of inspection conflict
630                                         database_build_escape_inspect_conflict "$origin"
631                                         # Check the change of the port option from the default
632                                         tmp_portsdb_work=${TMPDIR}/database_build_inspect_dependencies:portsdb_work
633                                         tmp_portopt=${TMPDIR}/database_build_inspect_dependencies:portopt
634                                         [ -d "$tmp_portsdb_work" ] || mkdir "$tmp_portsdb_work"
635                                         ( set -e
636                                                 export PORT_DBDIR=$tmp_portsdb_work
637                                                 export __MAKE_CONF=
638                                                 if database_build_make "$origin" showconfig > $tmp_portopt
639                                                 then
640                                                         cp "$tmp_portopt" "$dbpath"/ports_options.default
641                                                 else
642                                                         cat "$tmp_portopt" >&2
643                                                         message_echo 'Error in detecting the default options.' 2>&1
644                                                         exit 1
645                                                 fi
646                                         )
647                                         if [ `wc -c < $dbpath/ports_options.default` -gt 0 ]
648                                         then
649                                                 if database_build_make "$origin" showconfig > $tmp_portopt
650                                                 then
651                                                         cp "$tmp_portopt" "$dbpath"/ports_options.current
652                                                 else
653                                                         cat "$tmp_portopt" >&2
654                                                         message_echo 'Error in detecting the current options.' 2>&1
655                                                         exit 1
656                                                 fi
657                                         else
658                                                 cp /dev/null "$dbpath/ports_options.current"
659                                         fi
660                                         pkgsys_save_port_option_timestamp "$origin"
661                                         # Get the lists of requirements in the flavored form
662                                         database_build_create_pkgtag "$origin"
663                                         for variable in PKG_DEPENDS EXTRACT_DEPENDS PATCH_DEPENDS FETCH_DEPENDS BUILD_DEPENDS LIB_DEPENDS
664                                         do
665                                                 database_build_make "$origin" -V $variable
666                                         done > ${TMPDIR}/database_build_inspect_dependencies:build_depends_list
667                                         for variable in LIB_DEPENDS RUN_DEPENDS
668                                         do
669                                                 database_build_make "$origin" -V $variable
670                                         done > ${TMPDIR}/database_build_inspect_dependencies:run_depends_list
671                                         for tag in run build
672                                         do
673                                                 tr ' ' '\n' < ${TMPDIR}/database_build_inspect_dependencies:${tag}_depends_list | \
674                                                         sed -E 's#.*:([^:/]+/[^:/]+|[^:/]+/[^:/]+:[^:/]*)$#\1#' | cut -d : -f 1 | sort -u | \
675                                                         env LANG=C grep -Ev "`pkgsys_pkgtools_ports_filter_regexp`" \
676                                                                 | while read origin_flavor_incomplete
677                                                                 do
678                                                                         ( set -e
679                                                                                 opt_apply_default_config=yes
680                                                                                 database_build_determine_port_option "$origin_flavor_incomplete"
681                                                                         )
682                                                                         database_build_determine_flavored_origin "$origin_flavor_incomplete"
683                                                                 done | env LANG=C grep -v '^$' | sort -u > $dbpath/requirements.$tag.orig || :
684                                                 sed -E -f "${DBDIR}/conf/REPLACE.sed_pattern" "$dbpath/requirements.$tag.orig" \
685                                                         | env LANG=C grep -v '^$' | sort -u > $dbpath/requirements.$tag.src || :
686                                         done
687                                         for stage in orig src
688                                         do
689                                                 sort -u "$dbpath/requirements.run.${stage}" "$dbpath/requirements.build.${stage}" \
690                                                         > $dbpath/requirements.all.direct.${stage}
691                                                 mv "$dbpath/requirements.build.${stage}" "$dbpath/requirements.build.direct.${stage}"
692                                                 mv "$dbpath/requirements.run.${stage}" "$dbpath/requirements.run.direct.${stage}"
693                                         done
694                                         # Record the completion
695                                         touch "$dbpath/complete_as_node"
696                                         fileedit_rm_a_line "$origin_orig" "${DBDIR}/to_be_reconf"
697                                         fileedit_rm_a_line "$origin" "${DBDIR}/to_be_reconf"
698                                         # Restoration of escaped inspection conflict
699                                         database_build_restore_inspect_conflict "$origin"
700                                 else
701                                         # Restoration of escaped inspection conflict
702                                         database_build_restore_inspect_conflict "$origin"
703                                         # Reset the complied lists of requirements
704                                         for level in direct full
705                                         do
706                                                 for tag in run build
707                                                 do
708                                                         rm -f "$dbpath/requirements.${tag}.${level}"
709                                                 done
710                                         done
711                                         for origin_tmp in "$origin" "$origin_orig"
712                                         do
713                                                 for inspected_level_tmp in full direct node
714                                                 do
715                                                         fileedit_rm_a_line "$origin_tmp" "${DBDIR}/ports.inspected.${inspected_level_tmp}.list"
716                                                 done
717                                         done
718                                 fi
719                                 # Inspect the requirements
720                                 inspected_level=`database_build_get_inspected_level "$origin" "$origin_dependent"`
721                                 case $inspected_level in
722                                 full )
723                                         env LANG=C grep -v -Fx -f "${DBDIR}/installed_ports" \
724                                                 "$dbpath/requirements.all.direct.src" > ${TMPDIR}/missing.$origin_id || :
725                                         inspected_levels_compatible='full direct node'
726                                         ;;
727                                 direct )
728                                         env LANG=C grep -v -Fx -f "${DBDIR}/installed_ports" \
729                                                 "$dbpath/requirements.all.direct.src" > ${TMPDIR}/missing.$origin_id || :
730                                         inspected_levels_compatible='direct node'
731                                         ;;
732                                 node )
733                                         cp /dev/null "${TMPDIR}/missing.$origin_id"
734                                         inspected_levels_compatible='node'
735                                         ;;
736                                 esac
737                                 rm -rf "$dbpath/rename_requirements.sed.pattern"
738                                 nlines=`wc -l < ${TMPDIR}/missing.$origin_id`
739                                 iline=1
740                                 while [ $iline -le $nlines ]
741                                 do
742                                         origin_dependency=`sed -n ${iline}p "${TMPDIR}/missing.$origin_id"`
743                                         iline=$(($iline+1))
744                                         env LANG=C grep -q -Fx "$origin_dependency" "${DBDIR}/ports.inspected.list" 2> /dev/null && \
745                                                         continue
746                                         database_build_inspect_dependencies "$origin_dependency" "$origin"
747                                 done
748                                 if [ -e "$dbpath/rename_requirements.sed.pattern" ]
749                                 then
750                                         for tag in run build all
751                                         do
752                                                 sed -E -i .unrenamed -f "$dbpath/rename_requirements.sed.pattern" "$dbpath/requirements.${tag}.direct.src"
753                                         done
754                                 fi 
755                                 rm -f "${TMPDIR}/missing.$origin_id"
756                                 # Inspect the distfiles
757                                 dist_subdir_rpl=`database_query_get_makevar_val "$origin" DIST_SUBDIR | str_escape_replaceval_filter` || :
758                                 [ -n "$dist_subdir_rpl" ] && dist_subdir_rpl="$dist_subdir_rpl\/"
759                                 database_build_make "$origin" fetch-urlall-list \
760                                         | sed -E "s/.*\/([^\/]+)$/$dist_subdir_rpl\1/" \
761                                         | sort -u | fileedit_add_lines_if_new "${DBDIR}/distfiles.inspected"
762                                 # Transfer data from the previous database if existent, successful and no change
763                                 pkg_new=`cat "$dbpath/new_version"`
764                                 if [ ! -e "$dbpath/conf_updated" -a -d "$dbpath_prev" ] && pkg_info_e "$pkg_new" 2> /dev/null && \
765                                         ! env LANG=C grep -qFx "$origin" "$dbpath_prev/to_be_reconf" 2> /dev/null
766                                 then
767                                         same_as_prevset=yes
768                                         for dbfile in new_version CONFLICT.conf BUILDCONFLICT.conf MARG.conf MENV.conf \
769                                                 ports_options.default ports_options.current \
770                                                 rename_requirements.sed.pattern \
771                                                 requirements.run.direct.orig requirements.run.direct.src \
772                                                 requirements.build.direct.orig requirements.build.direct.src
773                                         do
774                                                 [ ! -e "$dbpath/$dbfile" -a ! -e "$dbpath_prev/$dbfile" ] && continue
775                                                 if ! diff "$dbpath/$dbfile"  "$dbpath_prev/$dbfile" 2> /dev/null > /dev/null
776                                                 then
777                                                         same_as_prevset=no
778                                                         break
779                                                 fi
780                                         done
781                                         if [ $same_as_prevset = yes ]
782                                         then
783                                                 nlines=`wc -l < $dbpath/requirements.all.direct.src`
784                                                 iline=1
785                                                 while [ $iline -le $nlines ]
786                                                 do
787                                                         origin_dependency=`sed -n ${iline}p "$dbpath/requirements.all.direct.src"`
788                                                         iline=$(($iline+1))
789                                                         if [ ! -e "${DBDIR}/requires/$origin_dependency/same_as_prevset" ]
790                                                         then
791                                                                 same_as_prevset=no
792                                                                 break
793                                                         fi
794                                                 done
795                                         fi
796                                         if [ $same_as_prevset = yes ]
797                                         then
798                                                 for dbfile in failed.list damaged_package manually_done.list
799                                                 do
800                                                         if env LANG=C grep -qFx "$origin" "${DBDIR}/prevset/$dbfile" 2> /dev/null
801                                                         then
802                                                                 same_as_prevset=no
803                                                                 break
804                                                         fi
805                                                 done
806                                         fi
807                                         if [ $same_as_prevset = yes ]
808                                         then
809                                                 rm -rf "$dbpath"
810                                                 cp -Rp "$dbpath_prev" "$dbpath"
811                                                 if [ -d "${DBDIR}/prevset/notes/$origin" ]
812                                                 then
813                                                         rm -rf "${DBDIR}/notes/$origin"
814                                                         mkdir -p "${DBDIR}/notes"
815                                                         cp -Rp "${DBDIR}/prevset/notes/$origin" "${DBDIR}/notes/$origin"
816                                                 fi
817                                                 {
818                                                         for tag in all run build none
819                                                         do
820                                                                 for level in full direct
821                                                                 do
822                                                                         echo "success.$tag.$level.list"
823                                                                 done
824                                                         done
825                                                 } | while read dbfile
826                                                 do
827                                                         if env LANG=C grep -Fxq "$origin" "${DBDIR}/prevset/$dbfile" 2> /dev/null
828                                                         then
829                                                                 fileedit_add_a_line_if_new "$origin" "${DBDIR}/$dbfile"
830                                                         fi
831                                                 done
832                                                 touch "$dbpath/same_as_prevset"
833                                                 message_echo "${DEPTH_INDEX}  ===> No update from the previous reinstallation. Progress status inherited."
834                                         fi
835                                 fi
836                                 # Record the completion
837                                 if [ "x$origin_orig" != "x$origin" ]
838                                 then
839                                         for inspected_level_tmp in $inspected_levels_compatible
840                                         do
841                                                 fileedit_add_a_line_if_new "$origin" "${DBDIR}/ports.inspected.${inspected_level_tmp}.list"
842                                         done
843                                         fileedit_add_a_line_if_new "$origin" "${DBDIR}/ports.inspected.list"
844                                         fileedit_add_a_line_if_new "$origin" "${DBDIR}/inspected_ports.update"
845                                         fileedit_rm_a_line "$origin" "${DBDIR}/stage.loop_list/ports_to_inspect.remain"
846                                 fi
847                                 fileedit_add_a_line_if_new "$origin" "${DBDIR}/done_required_ports_to_inspect"
848                         else
849                                 message_echo "${DEPTH_INDEX}  ===> Already inspected merged port"
850                                 fileedit_rm_a_line "$origin_orig" "${DBDIR}/to_be_reconf"
851                                 for inspected_level_tmp in full direct node
852                                 do
853                                         fileedit_rm_a_line "$origin_orig" "${DBDIR}/ports.inspected.${inspected_level_tmp}.list"
854                                 done
855                         fi
856                 fi
857                 # Record the completion
858                 for inspected_level_tmp in $inspected_levels_compatible
859                 do
860                         fileedit_add_a_line_if_new "$origin_orig" "${DBDIR}/ports.inspected.${inspected_level_tmp}.list"
861                 done
862                 fileedit_add_a_line_if_new "$origin_orig" "${DBDIR}/ports.inspected.list"
863                 fileedit_add_a_line_if_new "$origin_orig" "${DBDIR}/inspected_ports.update"
864                 fileedit_rm_a_line "$origin_orig" "${DBDIR}/stage.loop_list/ports_to_inspect.remain"
865                 message_echo "${DEPTH_INDEX}  ===> ok"
866                 DEPTH_INDEX=${DEPTH_INDEX_orig}
867         fi
868         if [ -n "$origin_dependent" -a "x$origin_orig" != "x$origin" ]
869         then
870                 origin_orig_regexp=`str_escape_regexp "$origin_orig"`
871                 origin_replace=`str_escape_replaceval "$origin"`
872                 fileedit_add_a_line_if_new "s/^$origin_orig_regexp$/$origin_replace/" "${DBDIR}/requires/$origin_dependent/rename_requirements.sed.pattern"
873         fi
874 }
875
876 # ============= Filter ignored dependencies from a list given by the standard input =============
877 database_build_filter_ignored_requirements ()
878 {
879         local origin pattern
880         origin=$1
881         pattern=${DBDIR}/requires/$origin/ignored_requirements.filter
882         if [ -e "$pattern" ]
883         then
884                 env LANG=C grep -Fxvq -f "$pattern"
885         else
886                 cat
887         fi 2> /dev/null || :
888 }
889
890 # ============= Build and get a list of the complete recursive dependencies of a port =============
891 database_build_get_complete_recursive_dependency ()
892 {
893         local tag origin suffix tmppath dbpath srcfile dstfile num_parents loophead dstfile_tmp tmpdstpath index_loop loop_len origin_target origin_ref dbpath_target
894         tag=$1
895         origin=$2
896         suffix=$3
897         tmppath=${TMPDIR}/database_build_get_complete_recursive_dependency
898         dbpath=${DBDIR}/requires/$origin
899         srcfile=$dbpath/requirements.${tag}.direct${suffix}
900         dstfile=$dbpath/requirements.${tag}.full${suffix}
901         if [ ! -e "$srcfile" ]
902         then
903                 [ -d "$dbpath" ] && rm -f "$dstfile"
904                 return 0
905         fi
906         if [ ! -e "$dstfile" ]
907         then
908                 touch "$tmppath.parents"
909                 num_parents=`wc -l < $tmppath.parents`
910                 if env LANG=C grep -Fxq "$origin" "$tmppath.parents"
911                 then
912                         loophead=`env LANG=C grep -Fxn "$origin" "$tmppath.parents" | tail -n 1 | cut -d : -f 1`
913                         if [ "x$opt_force_continuation_for_looped_dependency" = xno ]
914                         then
915                                 message_echo "ERROR: The following loop was found for requirements.${tag}${suffix}:" >&2
916                         else
917                                 message_echo "WARNING: The following loop was found for requirements.${tag}${suffix}:" >&2
918                         fi
919                         message_echo "  $origin" >&2
920                         ports_in_loop=`sed -n $(($loophead+1)),\$p "$tmppath.parents"`
921                         echo "$ports_in_loop" | sed 's/^/  -->/' | message_cat >&2
922                         message_echo "  -->$origin" >&2
923                         if [ "x$opt_disallow_force_continuation_for_looped_dependency" = xyes ]
924                         then
925                                 message_echo 'Resolve the problem manually and then retry by executing' >&2
926                                 message_echo "        ${APPNAME} reset keepopts" >&2
927                                 message_echo "        ${APPNAME}" >&2
928                                 exit 1
929                         else
930                                 message_echo 'Exploring a node port to terminate the loop by evaluating only build-and-run-time dependencies as essential ones.' >&2
931                                 echo "$origin" > $tmppath.ports_in_loop
932                                 echo "$ports_in_loop" >> $tmppath.ports_in_loop
933                                 echo "$origin" >> $tmppath.ports_in_loop
934                                 index_loop=1
935                                 loop_len=`wc -l < $tmppath.ports_in_loop`
936                                 while [ $index_loop -lt $loop_len ]
937                                 do
938                                         origin_target=`sed -n ${index_loop}p "$tmppath.ports_in_loop"`
939                                         origin_ref=`sed -n $((${index_loop}+1))p "$tmppath.ports_in_loop"`
940                                         dbpath_target=${DBDIR}/requires/$origin_target
941                                         if ! env LANG=C grep -Fxq "$origin_ref" "$dbpath_target/requirements.run.direct${suffix}" 2> /dev/null || \
942                                                 ! env LANG=C grep -Fxq "$origin_ref" "$dbpath_target/requirements.build.direct${suffix}" 2> /dev/null
943                                         then
944                                                 message_echo 'INFO: The dependency of '$origin_target' on '$origin_ref' is ignored to terminate the loop.' >&2
945                                                 break
946                                         fi
947                                         index_loop=$((${index_loop}+1))
948                                 done
949                                 if [ $index_loop -eq $loop_len ]
950                                 then
951                                         message_echo 'WARNING: The loop cannot be resolved. Continuing by forcible ignorance of the dependency of '$origin_target' on '$origin_ref'. This may cause confusion in the later processes.' >&2
952                                 fi
953                                 for suffix_tmp in '' .orig
954                                 do
955                                         for tag_tmp in run build
956                                         do
957                                                 env LANG=C grep -Fxq "$origin_ref" "$dbpath_target/requirements.${tag_tmp}.direct${suffix_tmp}" 2> /dev/null && \
958                                                         fileedit_add_a_line_if_new "$origin_ref" "$dbpath_target/ignored_requirements.${tag_tmp}${suffix_tmp}"
959                                         done
960                                         cat "$dbpath_target/ignored_requirements.run${suffix_tmp}" "$dbpath_target/ignored_requirements.build${suffix_tmp}" 2> /dev/null | sort -u > $dbpath_target/ignored_requirements.all${suffix_tmp}
961                                 done
962                                 cat "$dbpath_target/ignored_requirements.all"* 2> /dev/null | sort -u > $dbpath_target/ignored_requirements.filter
963                         fi
964                 fi
965                 echo "$origin" >> $tmppath.parents
966                 tmpdstpath=${TMPDIR}/requires/$origin
967                 dstfile_tmp=$tmpdstpath/requirements.${tag}.full${suffix}
968                 mkdir -p "$tmpdstpath"
969                 database_build_filter_ignored_requirements "$origin" < $srcfile | while read origin_requirement
970                 do
971                         # The least requirements of build are the direct build-time requirements and the full run-time requirements of the direct build-time requirements.
972                         tag_dep=$tag
973                         [ "x$tag" = xbuild ] && tag_dep=run
974                         recursive_dependency=`database_build_get_complete_recursive_dependency "$tag_dep" "$origin_requirement" "$suffix"`
975                         [ -e "$dbpath/ignored_requirements.filter" ] && \
976                                 echo "$origin_requirement" | env LANG=C grep -Fxq -f "$dbpath/ignored_requirements.filter" 2> /dev/null && \
977                                 continue
978                         echo "$origin_requirement"
979                         echo "$recursive_dependency"
980                 done > $dstfile_tmp
981                 sed -n ${num_parents}p "$tmppath.parents" > $tmppath.parents.tmp
982                 mv "$tmppath.parents.tmp" "$tmppath.parents"
983                 if [ ! -e "$dstfile" ]
984                 then
985                         sort -u "$dstfile_tmp" | env LANG=C grep -v '^$' > $dstfile || :
986                         rm "$dstfile_tmp"
987                 fi
988         fi
989         cat "$dstfile"
990 }
991
992 # ============= Inspect the necessity of requirements of a necessary port even in case of skipping unchanged ports =============
993 # Here the "necessity" means that a port must be kept installed, newly installed or reinstalled for run- or build-time operations.
994 # In other words, "unnecessary" ports are what are not yet installed and not required by any "necessary" ports neither in run- or build-time.
995 database_build_inspect_necessity_for_only_new_upgrade ()
996 {
997         local origin level dbpath tmpfile
998         origin=$1
999         level=$2
1000         dbpath=${DBDIR}/requires/$origin
1001         [ ! -d "$dbpath" -o -e "$dbpath/necessary_port.${level}" ] && return
1002         tmpfile=${TMPDIR}/database_build_inspect_necessity_for_only_new_upgrade:`echo "$origin" | tr / :`
1003         if database_query_does_a_port_need_update "$origin"
1004         then
1005                 sort -u "$dbpath/requirements.build.direct" "$dbpath/requirements.run.${level}" || :
1006         else
1007                 cat "$dbpath/requirements.run.${level}" || :
1008         fi 2> /dev/null | database_build_filter_ignored_requirements "$origin" > $tmpfile
1009         while read origin_requirement
1010         do
1011                 database_build_inspect_necessity_for_only_new_upgrade "$origin_requirement" "$level"
1012         done < $tmpfile
1013         rm "$tmpfile"
1014         touch "$dbpath/necessary_port.${level}"
1015 }
1016
1017 # ============= Build complement relations to new dependents for targets recursively =============
1018 database_build_complement_to_new_dependents_for_targets ()
1019 {
1020         local origin dbdir reqdir level
1021         origin=$1
1022         dbdir=${DBDIR}/targets/$origin
1023         reqdir=${DBDIR}/requires/$origin
1024         [ -d "$dbdir" ] || return 0
1025         echo "$origin" >> ${DBDIR}/stage.loop_list/parse_target_attr_info
1026         if [ -e "$dbdir/target_itself" ] && database_query_does_a_port_need_update "$origin"
1027         then
1028                 for level in direct full
1029                 do
1030                         cat "$reqdir/requirements.all.${level}" 2> /dev/null | \
1031                                 database_build_filter_ignored_requirements "$origin" | \
1032                                 while read origin_requirement
1033                         do
1034                                 fileedit_add_a_line_if_new "$origin" \
1035                                         "${DBDIR}/targets/$origin_requirement/complement_for_new_dependents.${level}"
1036                         done
1037                 done
1038                 cat "$reqdir/requirements.all.direct" "$reqdir/requirements.all.full" 2> /dev/null | \
1039                         sort -u | database_build_filter_ignored_requirements "$origin" | \
1040                         while read origin_requirement
1041                 do
1042                         database_build_complement_to_new_dependents_for_targets "$origin_requirement"
1043                 done
1044         fi
1045 }
1046
1047 # ============= Recursively complete necessary upgrades for build =============
1048 database_build_complete_necessary_upgrades_for_build ()
1049 {
1050         local origin level dbpath origin_requirement dbpath_requirement
1051         origin=$1
1052         level=$2
1053         dbpath=${DBDIR}/requires/$origin
1054         [ -e "$dbpath/requirements.build.${level}" ] || return 0
1055         while read origin_requirement
1056         do
1057                 dbpath_requirement=${DBDIR}/requires/$origin_requirement
1058                 [ -e "$dbpath_requirement/necessary_upgrade.build.${level}" ] || continue
1059                 [ `cat "${DBDIR}/moved_from/$origin_requirement/current_version" 2> /dev/null | wc -l` -eq 0 ] || continue
1060                 touch "$dbpath_requirement/necessary_upgrade.run.${level}"
1061                 database_build_complete_necessary_upgrades_for_build "$origin_requirement" "$level"
1062         done < $dbpath/requirements.build.${level}
1063         :
1064 }
1065
1066 # ============= Build target attribute files recursively =============
1067 database_build_target_attributes ()
1068 {
1069         local origin dbdir reqdir _is_target _is_requires_requirements _is_initial_requirements _is_requires_dependents _is_initial_dependents _is_requires_requirements_complement _is_relevant tag level database table
1070         origin=$1
1071         dbdir=${DBDIR}/targets/$origin
1072         reqdir=${DBDIR}/requires/$origin
1073         [ -d "$dbdir" ] || return 0
1074         [ -e "$dbdir/COMPLETE_ATTRS" ] && return
1075         _is_target=
1076         [ -e "$dbdir/target_itself" ] && _is_target=y
1077         for tag in all run build none
1078         do
1079                 for level in direct full
1080                 do
1081                         _is_relevant=${_is_target}
1082                         _is_requires_requirements=
1083                         _is_initial_requirements=
1084                         _is_requires_dependents=
1085                         _is_initial_dependents=
1086                         _is_requires_requirements_complement=
1087                         for database in requires initial
1088                         do
1089                                 for table in requirements dependents
1090                                 do
1091                                         if [ -e "$dbdir/target_${database}_${table}.${tag}.${level}" ]
1092                                         then
1093                                                 eval _is_${database}_${table}=y
1094                                                 _is_relevant=y
1095                                         fi
1096                                 done
1097                         done
1098                         if [ -z "${_is_requires_requirements}" -a -e "$dbdir/complement_for_new_dependents.${level}" ]
1099                         then
1100                                 _is_requires_requirements_complement=y
1101                                 _is_relevant=y
1102                         fi
1103                         [ -n "${_is_relevant}" ] && cat > $dbdir/attrs.${tag}.${level} << eof
1104 _is_target=${_is_target}
1105 _is_requires_requirements=${_is_requires_requirements}
1106 _is_initial_requirements=${_is_initial_requirements}
1107 _is_requires_dependents=${_is_requires_dependents}
1108 _is_initial_dependents=${_is_initial_dependents}
1109 _is_requires_requirements_complement=${_is_requires_requirements_complement}
1110 eof
1111                 done
1112         done
1113         touch "$dbdir/COMPLETE_ATTRS"
1114 }
1115
1116 # ============= Order the ports considering dependencies =============
1117 database_build_order_ports_considering_dependencies ()
1118 {
1119         touch "${DBDIR}/reinst_order.list.tmp"
1120         (cd "${DBDIR}/requires" && \
1121                 find . -depth 3 -name requirements.all.full -exec echo {} \; -exec cat {} \; -exec echo \;) | \
1122                 env "DBDIR=${DBDIR}" awk -f "${LIBEXECDIR}"/order_dependencies.awk || return
1123         env LANG=C grep -v '^$' "${DBDIR}/reinst_order.list.tmp" > "${DBDIR}/reinst_order.list" || :
1124 }
1125
1126 # ============= [Sub-function] Common operations for resetting configurations for a port =============
1127 _database_build_reset_a_port_confdb ()
1128 {
1129         local origin origin_replace db
1130         origin=$1
1131         [ -d "${DBDIR}/initial/$origin" -o -d "${DBDIR}/replace/$origin" \
1132                 -o -d "${DBDIR}/requires/$origin" -o -d "${DBDIR}/targets/$origin" ] || return 0
1133         touch "${DBDIR}/inspected_ports_only_partially"
1134         {
1135                 echo "$origin"
1136                 cat "${DBDIR}/replace/$origin/origin" 2> /dev/null || :
1137                 for dbtag in initial requires
1138                 do
1139                         for tabel in requirements dependents
1140                         do
1141                                 cat "${DBDIR}/$dbtag/$origin/$tabel.all.full" 2> /dev/null || :
1142                                 cat "${DBDIR}/$dbtag/$origin/$tabel.all.full.orig" 2> /dev/null || :
1143                                 rm -rf "${DBDIR}/$dbtag/$origin/$tabel.run.full" \
1144                                         "${DBDIR}/$dbtag/$origin/$tabel.build.full"
1145                         done
1146                         rm -rf "${DBDIR}/$dbtag/$origin/is_customized"
1147                 done
1148         } | sort -u >> ${DBDIR}/inspected_ports.update
1149         for level in full direct node
1150         do
1151                 fileedit_rm_a_line "$origin" "${DBDIR}/ports.inspected.${level}.list"
1152         done
1153         fileedit_rm_a_line "$origin" "${DBDIR}/obsolete_ports"
1154         fileedit_rm_a_line "$origin" "${DBDIR}/moved_ports"
1155         fileedit_rm_a_line "$origin" "${DBDIR}/ports.inspected.list"
1156         cat "${DBDIR}/replace/$origin/origin" 2> /dev/null || :
1157 }
1158
1159 # ============= Clear database directories for a flavored origin =============
1160 database_build_clear_db_dirs ()
1161 {
1162         local origin db
1163         origin=$1
1164         for db in requires replace targets obsolete
1165         do
1166                 rm -rf "${DBDIR}/$db/$origin"
1167         done
1168 }
1169
1170 # ============= Remove configurations for a port permanently =============
1171 database_build_forget ()
1172 {
1173         local origin origin_replace
1174         origin=$1
1175         origin_replace=`_database_build_reset_a_port_confdb "$origin"`
1176         fileedit_rm_a_line "$origin" "${DBDIR}/targets_specified_so_far"
1177         [ -z "$origin_replace" ] || database_build_forget "$origin_replace"
1178         database_build_clear_db_dirs "$origin"
1179 }
1180
1181 # ============= Overlay onto the temporary database so as to re-inspect and reinstall ports whose configurations were changed =============
1182 database_build_patch_reconf ()
1183 {
1184         local origin origin_replace
1185         origin=$1
1186         origin_replace=`_database_build_reset_a_port_confdb "$origin"`
1187         [ -d "${DBDIR}/initial/$origin" -o -d "${DBDIR}/requires/$origin" ] && \
1188                 fileedit_add_a_line_if_new "$origin" "${DBDIR}/stage.loop_list/ports_to_inspect"
1189         fileedit_add_a_line_if_new "$origin" "${DBDIR}/to_be_reconf"
1190         fileedit_rm_a_line "$origin" "${DBDIR}/done_required_ports_to_inspect"
1191         [ -z "$origin_replace" ] || database_build_patch_reconf "$origin_replace"
1192         database_build_clear_db_dirs "$origin"
1193 }
1194
1195 # ============= Post-processes after finishing to inspect initial dependencies =============
1196 database_build_post_inspect_initial_dependencies ()
1197 {
1198         find "${DBDIR}/initial" -depth 2 -type d \
1199                 | sed -E 's|.*/([^/]+/[^/]+)$|\1|' > ${DBDIR}/inspected_ports.initial
1200 }
1201
1202 # ============= Post-processes after finishing to inspect dependencies =============
1203 database_build_post_inspect_dependencies ()
1204 {
1205         local table tmpfile
1206         tmpfile=${TMPDIR}/database_build_post_inspect_dependencies
1207         touch "${DBDIR}/obsolete_ports" "${DBDIR}/inspected_ports.update"
1208         find "${DBDIR}/requires" -depth 2 -type d \
1209                 | sed -E 's|.*/([^/]+/[^/]+)$|\1|' > ${DBDIR}/inspected_ports
1210         sort -u "${DBDIR}/inspected_ports" "${DBDIR}/inspected_ports.initial" > ${DBDIR}/inspected_ports.all
1211         {
1212                 cat "${DBDIR}/conf/HOLD:PORTS.parsed" || :
1213                 cat "${DBDIR}/need.list" || :
1214         } 2> /dev/null | sort -u > $tmpfile.obsolete_ports.exclude
1215         env LANG=C grep -v -Fx -f "$tmpfile.obsolete_ports.exclude" "${DBDIR}/obsolete_ports" > ${DBDIR}/obsolete_ports.can_be_deleted || :
1216         cp /dev/null "${DBDIR}/REPLACE.complete_sed_pattern.tmp"
1217         find "${DBDIR}/replace" -depth 3 -type f -name origin | while read nodepath
1218         do
1219                 origin_orig=`expr "$nodepath" : '.*/\([^/][^/]*/[^/][^/]*\)/origin$'`
1220                 origin=`cat "$nodepath"`
1221                 origin_orig_regexp=`str_escape_regexp "$origin_orig"`
1222                 origin_esc=`str_escape_replaceval "$origin"`
1223                 echo "s/^$origin_orig_regexp$/$origin_esc/" >> ${DBDIR}/REPLACE.complete_sed_pattern.tmp
1224         done
1225         mv "${DBDIR}/REPLACE.complete_sed_pattern.tmp" "${DBDIR}/REPLACE.complete_sed_pattern"
1226         if [ `cat "${DBDIR}/inspected_ports.update" 2> /dev/null | wc -l` -gt 0 ]
1227         then
1228                 env LANG=C grep -Fx -f "${DBDIR}/inspected_ports.all" "${DBDIR}/inspected_ports.update" \
1229                         > ${DBDIR}/inspected_ports.update.tmp 2> /dev/null || :
1230                 mv "${DBDIR}/inspected_ports.update.tmp" "${DBDIR}/inspected_ports.update"
1231                 if [ $opt_only_target_scope = yes ]
1232                 then
1233                         touch "${DBDIR}/inspected_ports_only_partially"
1234                 else
1235                         rm -f "${DBDIR}/inspected_ports_only_partially"
1236                 fi
1237                 if program_chk_stage_loop_complete CONVERT_REQUIREMENTS_LIST
1238                 then
1239                         mv "${DBDIR}/inspected_ports.update" "${DBDIR}/stage.loop_list/convert_dependency_lists"
1240                 else
1241                         cat "${DBDIR}/inspected_ports.update" "${DBDIR}/stage.loop_list/convert_dependency_lists" \
1242                                 2> /dev/null | sort -u > ${DBDIR}/stage.loop_list/convert_dependency_lists.tmp
1243                         mv "${DBDIR}/stage.loop_list/convert_dependency_lists.tmp" \
1244                                 "${DBDIR}/stage.loop_list/convert_dependency_lists"
1245                         rm -f "${DBDIR}/inspected_ports.update"
1246                 fi
1247         else
1248                 program_chk_stage_loop_complete CONVERT_REQUIREMENTS_LIST \
1249                         && rm -f "${DBDIR}/stage.loop_list/convert_dependency_lists"
1250         fi
1251         {
1252                 sed -E -f "${DBDIR}/REPLACE.complete_sed_pattern" "${DBDIR}/need.list" || :
1253                 cat "${DBDIR}/need.list" || :
1254         } 2> /dev/null | sort -u > ${DBDIR}/need.with_replaced.list
1255         for table in requirements dependents itself
1256         do
1257                 [ -e "${DBDIR}/stage.loop_list/target_$table.specified" ] || continue
1258                 sed -E -f "${DBDIR}/REPLACE.complete_sed_pattern" \
1259                         "${DBDIR}/stage.loop_list/target_$table.specified" \
1260                         > ${DBDIR}/stage.loop_list/target_$table.replaced.specified
1261         done
1262         cp /dev/null "${DBDIR}/update_dependencies"
1263 }