OSDN Git Service

81a8feaa708e9b7abd300f95344490cc97b64995
[portsreinstall/current.git] / lib / libcommand_do.sh
1 #!/bin/sh -e
2 # ==============================================================================
3 # portsreinstall library script
4 # - "do"/"redo" command operation -
5 # Copyright (C) 2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
6 # This software is distributed under the 2-Clause BSD License.
7 # ==============================================================================
8
9 # ============= Operation of redo command before the database reconstruction =============
10 command_do_do__command_all_exec_command_specific_preconfiguration ()
11 {
12         program_deregister_stage_complete FORGET::PREPARATION_INSPECT_MASTER
13         program_deregister_stage_complete ALL_COMPLETE
14 }
15
16 # ============= Operation of redo command before the database reconstruction =============
17 command_do_redo__command_all_exec_command_specific_preconfiguration ()
18 {
19         program_deregister_stage_complete REDO_INIT
20         if [ $opt_reset_targets = yes ]
21         then
22                 program_deregister_stage_complete DETERMINE_SPECIFIED_TARGETS
23                 program_deregister_stage_complete PREPARE_FOR_INSPECT_ALL_DEPENDENCIES
24                 rm -rf "${DBDIR}/targets"
25         fi
26         command_do_do__command_all_exec_command_specific_preconfiguration
27 }
28
29 # ============= Meta process for redo =============
30 command_do_meta_process_for_redo ()
31 {
32         local PROGRAM_DEPENDS
33         PROGRAM_DEPENDS=''
34         _program_exec_and_record_completion__operation ()
35         {
36                 rm -f "${DBDIR}/new_success_in_current_run"
37                 [ "x$COMMAND_MODE" = xredo ] || return 0
38                 message_echo "[REDO mode]"
39                 message_echo
40         }
41         program_exec_and_record_completion REDO_INIT
42 }
43
44 # ============= Determine specified targets =============
45 command_do_determine_specified_targets ()
46 {
47         local PROGRAM_DEPENDS
48         PROGRAM_DEPENDS=''
49         _program_exec_and_record_completion__operation ()
50         {
51                 local tag level dbsuffix
52                 message_section_title "Determining specified targets"
53                 cat "${DBDIR}/stage.loop_list/target_itself.specified" \
54                         "${DBDIR}/stage.loop_list/target_dependents.specified" \
55                         "${DBDIR}/stage.loop_list/target_requirements.specified" \
56                         "${DBDIR}/need.list" \
57                         "${DBDIR}/targets_specified_so_far" 2> /dev/null \
58                         | sort -u > ${DBDIR}/targets_specified_so_far.tmp
59                 mv "${DBDIR}/targets_specified_so_far.tmp" "${DBDIR}/targets_specified_so_far"
60                 rm -f "${DBDIR}/stage.loop_list/target_itself.specified" \
61                         "${DBDIR}/stage.loop_list/target_dependents.specified" \
62                         "${DBDIR}/stage.loop_list/target_requirements.specified"
63                 if [ -n "$opt_target_itself$opt_target_dependents$opt_target_requirements" ]
64                 then
65                         options_select_new_ports_if_duplicated O \
66                                 "${DBDIR}/stage.loop_list/target_itself.specified" "$opt_target_itself"
67                         options_select_new_ports_if_duplicated t \
68                                 "${DBDIR}/stage.loop_list/target_dependents.specified" "$opt_target_dependents"
69                         options_select_new_ports_if_duplicated T \
70                                 "${DBDIR}/stage.loop_list/target_requirements.specified" "$opt_target_requirements"
71                         if [ `cat "${DBDIR}/stage.loop_list/target_itself.specified" \
72                                 "${DBDIR}/stage.loop_list/target_dependents.specified" \
73                                 "${DBDIR}/stage.loop_list/target_requirements.specified" | wc -l` -eq 0 ]
74                         then
75                                 message_echo "ERROR: No matching port for target globs." >&2
76                                 message_echo >&2
77                                 exit 1
78                         fi
79                         cat "${DBDIR}/stage.loop_list/target_itself.specified" \
80                                 "${DBDIR}/stage.loop_list/target_dependents.specified" \
81                                 "${DBDIR}/stage.loop_list/target_requirements.specified" \
82                                 | sort -u > ${TMPDIR}/DETERMINE_SPECIFIED_TARGETS.reset
83                         cat "${TMPDIR}/DETERMINE_SPECIFIED_TARGETS.reset" "${DBDIR}/need.list" 2> /dev/null \
84                                 | sort -u > ${DBDIR}/need.list.tmp
85                         mv "${DBDIR}/need.list.tmp" "${DBDIR}/need.list"
86                         sort -u "${DBDIR}/need.list" "${DBDIR}/targets_specified_so_far" \
87                                 > ${DBDIR}/targets_specified_so_far.tmp
88                         mv "${DBDIR}/targets_specified_so_far.tmp" "${DBDIR}/targets_specified_so_far"
89                         for tag in all run build none
90                         do
91                                 for level in direct full
92                                 do
93                                         dbsuffix=$tag.$level
94                                         {
95                                                 cat "${TMPDIR}/DETERMINE_SPECIFIED_TARGETS.reset"
96                                                 cat "${DBDIR}/stage.loop_list/target_dependents.specified" | while read origin
97                                                 do
98                                                         nodedir=${DBDIR}/requires/$origin
99                                                         cat "$nodedir/dependents.$dbsuffix" 2> /dev/null
100                                                 done
101                                                 cat "${DBDIR}/stage.loop_list/target_requirements.specified" | while read origin
102                                                 do
103                                                         nodedir=${DBDIR}/requires/$origin
104                                                         cat "$nodedir/requirements.$dbsuffix" 2> /dev/null
105                                                 done
106                                         } | sort -u | while read origin
107                                         do
108                                                 fileedit_rm_a_line "$origin" "${DBDIR}/success.$dbsuffix.list"
109                                                 fileedit_rm_a_line "$origin" "${DBDIR}/todo_after_requirements_succeed.$dbsuffix.list"
110                                                 rm -f "${DBDIR}/requires/$origin/succeeded_once"
111                                         done
112                                 done
113                         done
114                 fi
115                 message_echo
116         }
117         program_exec_and_record_completion DETERMINE_SPECIFIED_TARGETS
118 }
119
120 # ============= Show specified targets =============
121 command_do_show_specified_targets ()
122 {
123         if [ -n "$opt_target_itself$opt_target_dependents$opt_target_requirements" -a $opt_batch_mode = no ]
124         then
125                 message_echo "INFO: (Re/de-)installation will be carried out only for the targets:"
126                 echo
127                 if [ `wc -l < ${DBDIR}/stage.loop_list/target_itself.specified` -gt 0 ]
128                 then
129                         message_echo "[Targets only]"
130                         echo "----------------------------------------"
131                         cat "${DBDIR}/stage.loop_list/target_itself.specified"
132                         echo "----------------------------------------"
133                         echo
134                 fi
135                 if [ `wc -l < ${DBDIR}/stage.loop_list/target_dependents.specified` -gt 0 ]
136                 then
137                         message_echo "[Targets with their `options_get_dependency_msgterm` dependents]"
138                         echo "----------------------------------------"
139                         cat "${DBDIR}/stage.loop_list/target_dependents.specified"
140                         echo "----------------------------------------"
141                         echo
142                 fi
143                 if [ `wc -l < ${DBDIR}/stage.loop_list/target_requirements.specified` -gt 0 ]
144                 then
145                         message_echo "[Targets with their `options_get_dependency_msgterm` requirements]"
146                         echo "----------------------------------------"
147                         cat "${DBDIR}/stage.loop_list/target_requirements.specified"
148                         echo "----------------------------------------"
149                         echo
150                 fi
151         fi
152 }
153
154 # ============= Determine all target ports =============
155 command_do_determine_all_target_ports ()
156 {
157         local PROGRAM_DEPENDS
158         PROGRAM_DEPENDS='DETERMINE_SPECIFIED_TARGETS COLLECT_ALL_INSTALLED_PACKAGES'
159         _program_exec_and_record_completion__operation ()
160         {
161                 message_section_title "Determining all target ports"
162                 {
163                         if [ $opt_only_target_scope = no ]
164                         then
165                                 cat "${DBDIR}/installed_ports" 2> /dev/null || :
166                         fi
167                         cat "${DBDIR}/stage.loop_list/target_itself.specified" || :
168                         cat "${DBDIR}/stage.loop_list/target_dependents.specified" || :
169                         cat "${DBDIR}/stage.loop_list/target_requirements.specified" || :
170                         cat "${DBDIR}/targets_specified_so_far" || :
171                 }  2> /dev/null | sort -u > "${DBDIR}/stage.loop_list/ports_to_inspect"
172                 cp "${DBDIR}/stage.loop_list/ports_to_inspect" "${DBDIR}/stage.loop_list/ports_to_inspect_initial"
173                 while read origin
174                 do
175                         [ -d "${PORTSDIR}/$origin" ] || echo "$origin"
176                 done < ${DBDIR}/stage.loop_list/ports_to_inspect > ${DBDIR}/obsoletes_to_escape_for_inspection
177                 message_echo
178         }
179         program_exec_and_record_completion DETERMINE_ALL_TARGET_PORTS
180 }
181
182 # ============= Inspection of all initial dependencies =============
183 command_do_inspection_of_all_initial_dependencies ()
184 {
185         local PROGRAM_DEPENDS
186         PROGRAM_DEPENDS='DETERMINE_ALL_TARGET_PORTS'
187         _program_exec_restartable_loop_operation__routine ()
188         {
189                 local origin
190                 origin=$1
191                 database_build_setup_initial_node "$origin"
192         }
193         _program_exec_and_record_completion__operation ()
194         {
195                 local DEPTH_INDEX 
196                 message_section_title "Inspecting initial dependencies of the all installed packages"
197                 [ $opt_only_target_scope = no -a -n "$opt_target_itself$opt_target_dependents$opt_target_requirements" ] && \
198                         message_echo "INFO: Ports which seem irrelevant to the targets are also inspected in order to get complete information."
199                 program_exec_restartable_loop_operation ports_to_inspect_initial
200                 database_build_post_inspect_initial_dependencies
201                 message_echo
202         }
203         program_exec_and_record_completion INSPECT_ALL_INITIAL_DEPENDENCIES
204 }
205
206 # ============= Prepare for inspecting all dependencies =============
207 command_do_prepare_for_inspect_all_dependencies ()
208 {
209         local PROGRAM_DEPENDS
210         PROGRAM_DEPENDS='PARSE_CONF  INSPECT_ALL_INITIAL_DEPENDENCIES'
211         _program_exec_and_record_completion__operation ()
212         {
213                 message_section_title "Preparing for inspection of all dependencies"
214                 database_build_escape "${DBDIR}/escaped_obsoletes" < ${DBDIR}/obsoletes_to_escape_for_inspection
215                 cp /dev/null "${DBDIR}/done_required_ports_to_inspect"
216                 message_echo
217         }
218         program_exec_and_record_completion PREPARE_FOR_INSPECT_ALL_DEPENDENCIES
219 }
220
221 # ============= Check ports of which the port options are changed and reset their databases =============
222 # Return status 0 for no need to update of inspected ports and 1 for needed to do it
223 command_do_reset_changed_portdb ()
224 {
225         local tmp_ls
226         program_chk_stage_complete INSPECT_DEPENDENTS || return
227         pkgsys_exists_saved_port_oprions_timestamps || return
228         message_section_title "Inspecting changes of port options"
229         tmp_ls=${TMPDIR}/command_do_reset_changed_portdb
230         rm -f "$tmp_ls.updated"
231         if [ ! -d "${PORT_DBDIR}" ]
232         then
233                 message_echo "WARNING: ${PORT_DBDIR} is missing. All port options are recognized as default."
234         fi
235         pkgsys_get_saved_port_oprions_timestamps_all > $tmp_ls.db
236         pkgsys_get_current_port_oprions_timestamp > $tmp_ls.log
237         pkgsys_get_changed_port_oprions "$tmp_ls.db" "$tmp_ls.log" > $tmp_ls.diff
238         if ! [ `wc -l < $tmp_ls.diff` -gt 0 ]
239         then
240                 message_echo
241                 return
242         fi
243         message_echo "INFO: There are some changes. Inspecting the detail..."
244         cp /dev/null "$tmp_ls.uninspected.dbfile"
245         cp /dev/null "$tmp_ls.uninspected.origin"
246         cp /dev/null "$tmp_ls.nonexistent.db"
247         pkgsys_conv_portoptiondbs_to_globs < $tmp_ls.diff > $tmp_ls.glob
248         str_escape_replaceval_filter < $tmp_ls.diff > $tmp_ls.diff.rpl
249         paste "$tmp_ls.diff" "$tmp_ls.diff.rpl" "$tmp_ls.glob" | while read -r dbfile dbfile_rpl glob
250         do
251                 pkgsys_eval_ports_glob "$glob" > $tmp_ls.origins
252                 if [ `wc -l < $tmp_ls.origins` -gt 0 ]
253                 then
254                         sed -E "s/^/$dbfile_rpl /" < $tmp_ls.origins
255                 else
256                         echo $dbfile >> $tmp_ls.nonexistent.db
257                 fi
258         done | while read dbfile origin
259         do
260                 if [ -d "${DBDIR}/requires/$origin" ]
261                 then
262                         message_echo "Change detected on $origin: Resetting"
263                         database_build_patch_reconf "$origin"
264                         program_deregister_stage_complete PREPARE_FOR_INSPECT_ALL_DEPENDENCIES
265                         program_deregister_stage_complete ALL_COMPLETE
266                         touch "$tmp_ls.updated"
267                 else
268                         echo "$dbfile" >> $tmp_ls.uninspected.dbfile
269                         echo "$origin" >> $tmp_ls.uninspected.origin
270                 fi
271         done
272         message_echo "INFO: Recording for not inspected ports..."
273         pkgsys_conv_portorigin_to_port_oprion_timestamp_logname < $tmp_ls.uninspected.origin > $tmp_ls.uninspected.logname
274         str_escape_regexp_filter < $tmp_ls.uninspected.dbfile | sed 's/^/^/;s/$/[[:space:]]/' > $tmp_ls.uninspected.dbfile_ptn
275         paste "$tmp_ls.uninspected.dbfile_ptn" "$tmp_ls.uninspected.logname" | while read -r dbfile_ptn logname
276         do
277                 grep -E "$dbfile_ptn" < $tmp_ls.log > ${DBDIR}/ls_dbdir/$logname.log 2> /dev/null || :
278         done
279         str_escape_regexp_filter < $tmp_ls.nonexistent.db | sed 's/^/^/;s/$/[[:space:]]/' > $tmp_ls.nonexistent.db_ptn
280         grep -E -f "$tmp_ls.nonexistent.db_ptn" < $tmp_ls.log | pkgsys_register_list_nonexistent_portopriondb
281         message_echo
282         [ ! -e "$tmp_ls.updated" ]
283 }
284
285 # ============= Inspection of all dependencies =============
286 command_do_inspection_of_all_dependencies ()
287 {
288         local PROGRAM_DEPENDS
289         PROGRAM_DEPENDS='PREPARE_FOR_INSPECT_ALL_DEPENDENCIES'
290         _program_exec_restartable_loop_operation__routine ()
291         {
292                 local origin
293                 origin=$1
294                 database_build_inspect_dependencies "$origin"
295         }
296         _program_exec_and_record_completion__operation ()
297         {
298                 local DEPTH_INDEX 
299                 message_section_title "Inspecting dependencies of the all installed packages"
300                 [ $opt_only_target_scope = no -a -n "$opt_target_itself$opt_target_dependents$opt_target_requirements" ] && \
301                         message_echo "INFO: Ports which seem irrelevant to the targets are also inspected in order to get complete information."
302                 DEPTH_INDEX='--'
303                 program_exec_restartable_loop_operation ports_to_inspect
304                 database_build_post_inspect_dependencies
305                 database_maintain_clear_prevset
306                 message_echo
307         }
308         program_exec_and_record_completion INSPECT_ALL_DEPENDENCIES
309 }
310
311 # ============= Convert dependency-lists to actual ones =============
312 command_do_convert_dependency_lists_to_actual_ones ()
313 {
314         local PROGRAM_DEPENDS
315         PROGRAM_DEPENDS='INSPECT_ALL_DEPENDENCIES'
316         _program_exec_restartable_loop_operation__routine ()
317         {
318                 local origin table dbtag level tag target
319                 origin=$1
320                 for table in dependents requirements
321                 do
322                         for dbtag in requires obsolete
323                         do
324                                 for level in direct full
325                                 do
326                                         for tag in all run build
327                                         do
328                                                 target=${DBDIR}/$dbtag/$origin/${table}.${tag}.${level}
329                                                 if [ -e "$target.src" ]
330                                                 then
331                                                         sed -E -f "${DBDIR}/REPLACE.complete_sed_pattern" "$target.src" \
332                                                                 | grep -v '^$' | sort -u > $target.tmp
333                                                         [ -e "$target" ] && ! diff -q "$target.tmp" "$target" > /dev/null \
334                                                                 && echo "$origin" >> ${DBDIR}/update_dependencies
335                                                         mv "$target.tmp" "$target"
336                                                 else
337                                                         [ -e "$target" ] && echo "$origin" >> ${DBDIR}/update_dependencies
338                                                         rm -f "$target"
339                                                 fi
340                                         done
341                                 done
342                         done
343                 done
344         }
345         _program_exec_and_record_completion__operation ()
346         {
347                 message_section_title "Conversion of dependency-lists to actual ones"
348                 program_exec_restartable_loop_operation convert_dependency_lists
349                 sort -u "${DBDIR}/update_dependencies" > ${DBDIR}/update_dependencies.tmp
350                 mv "${DBDIR}/update_dependencies.tmp" "${DBDIR}/update_dependencies"
351                 for tag in all run build
352                 do
353                         ( cd "${DBDIR}/requires" && \
354                                 find . -depth 3 -type f -name requirements.${tag}.full -or -name requirements.${tag}.full.orig ) \
355                                 | sort -u \
356                                 | sed 's|^./||;s|/[^/]*$||' \
357                                 | grep -v -Fx -f "${DBDIR}/update_dependencies" \
358                                 > ${TMPDIR}/convert_requirements_list:full_complete.grep_pattern || :
359                         ( cd "${DBDIR}/requires" && \
360                                 find . -depth 3 -type f -name requirements.${tag}.direct -or -name requirements.${tag}.direct.orig ) \
361                                 | sort -u \
362                                 | sed 's|^./||;s|/[^/]*$||' \
363                                 | grep -v -Fx -f "${TMPDIR}/convert_requirements_list:full_complete.grep_pattern" \
364                                 > ${DBDIR}/stage.loop_list/complete_recursive_${tag}time_reqlists || :
365                 done
366                 for inspected_level_tmp in direct node
367                 do
368                         cat "${DBDIR}/ports.inspected.${inspected_level_tmp}.list" || :
369                 done 2> /dev/null | sort -u > ${DBDIR}/stage.loop_list/trim_dependency_lists_rm_uninspected_ports
370                 find "${DBDIR}/requires" -depth 2 -type d > ${DBDIR}/stage.loop_list/inspect_dependent
371                 [ -e "${DBDIR}/dependents_files" ] && \
372                         mv "${DBDIR}/dependents_files" "${DBDIR}/dependents_files.prev"
373                 rm -f "${DBDIR}/stage.loop_list/make_dependents_lists_unique.tmp" "${DBDIR}/dependents_files.tmp"
374                 message_echo
375         }
376         program_exec_and_record_completion CONVERT_REQUIREMENTS_LIST
377 }
378
379 # ============= Completion of recursive requirement lists =============
380 command_do_completion_of_recursive_requirement_lists ()
381 {
382         local PROGRAM_DEPENDS _REQUIREMENT_LISTS_tag
383         for _REQUIREMENT_LISTS_tag in all run build
384         do
385                 PROGRAM_DEPENDS='CONVERT_REQUIREMENTS_LIST'
386                 _program_exec_restartable_loop_operation__routine ()
387                 {
388                         local tag dbpath origin suffix
389                         tag=${_REQUIREMENT_LISTS_tag}
390                         dbpath=$1
391                         origin=`str_dirpath_to_origin "$dbpath"`
392                         for suffix in '' .orig
393                         do
394                                 database_build_get_complete_recursive_dependency "$tag" "$origin" "$suffix" > /dev/null
395                         done
396                 }
397                 _program_exec_and_record_completion__operation ()
398                 {
399                         local tag
400                         tag=${_REQUIREMENT_LISTS_tag}
401                         message_section_title "Completion of ${tag}-time requirement lists"
402                         program_exec_restartable_loop_operation complete_recursive_${tag}time_reqlists
403                         message_echo
404                 }
405                 program_exec_and_record_completion RECURSIVE_REQUIREMENT_LISTS:${_REQUIREMENT_LISTS_tag}
406         done
407 }
408
409 # ============= Trim dependency lists by removing uninspected ports =============
410 command_do_trim_dependency_lists_by_removing_uninspected_ports ()
411 {
412         local PROGRAM_DEPENDS
413         if [ $opt_only_target_scope = yes ]
414         then
415                 PROGRAM_DEPENDS='INSPECT_ALL_DEPENDENCIES CONVERT_REQUIREMENTS_LIST'
416                 _program_exec_restartable_loop_operation__routine ()
417                 {
418                         local dbpath tag level srcdb
419                         dbpath=$1
420                         for tag in all run build
421                         do
422                                 for level in direct full
423                                 do
424                                         srcdb=requirements.${tag}.${level}
425                                         [ -e "$dbpath/$srcdb" ] || continue
426                                         grep -Fx -f "${DBDIR}/inspected_ports" "$dbpath/$srcdb" > $dbpath/$srcdb.tmp || :
427                                         mv "$dbpath/$srcdb.tmp" "$dbpath/$srcdb"
428                                 done
429                         done
430                 }
431                 _program_exec_and_record_completion__operation ()
432                 {
433                         message_section_title "Trimming dependency lists by removing uninspected ports"
434                         program_exec_restartable_loop_operation trim_dependency_lists_rm_uninspected_ports
435                         message_echo
436                 }
437                 program_exec_and_record_completion TRIM_DEPENDENCY_LISTS_RM_UNINSPECTED_PORTS
438         fi
439 }
440
441 # ============= Inspection of dependents =============
442 command_do_inspection_of_dependents ()
443 {
444         local PROGRAM_DEPENDS
445         PROGRAM_DEPENDS='INSPECT_ALL_DEPENDENCIES CONVERT_REQUIREMENTS_LIST TRIM_DEPENDENCY_LISTS_RM_UNINSPECTED_PORTS'
446         _program_exec_restartable_loop_operation__routine ()
447         {
448                 local dbpath origin tag level suffix srcdb dstdb
449                 dbpath=$1
450                 origin=`str_dirpath_to_origin "$dbpath"`
451                 for tag in all run build
452                 do
453                         for suffix in '' .orig
454                         do
455                                 for level in direct full
456                                 do
457                                         srcdb=requirements.${tag}.${level}${suffix}
458                                         [ -e "$dbpath/$srcdb" ] || continue
459                                         dstdb=dependents.${tag}.${level}${suffix}
460                                         while read origin_requirement
461                                         do
462                                                 dstpath=${DBDIR}/requires/$origin_requirement
463                                                 echo "$dstpath/$dstdb" >> ${DBDIR}/dependents_files.tmp
464                                                 [ "$dstpath/$dstdb" -nt "$dbpath/$srcdb" ] && continue
465                                                 mkdir -p "$dstpath"
466                                                 echo "$origin" >> $dstpath/$dstdb.raw
467                                                 echo "$dstpath/$dstdb" >> ${DBDIR}/stage.loop_list/make_dependents_lists_unique.tmp
468                                         done < $dbpath/$srcdb
469                                 done
470                                 srcdb=ignored_requirements.${tag}${suffix}
471                                 [ -e "$dbpath/$srcdb" ] || continue
472                                 dstdb=ignored_dependents.${tag}${suffix}
473                                 while read origin_requirement
474                                 do
475                                         dstpath=${DBDIR}/requires/$origin_requirement
476                                         echo "$dstpath/$dstdb" >> ${DBDIR}/ignored_dependents_files.tmp
477                                         [ "$dstpath/$dstdb" -nt "$dbpath/$srcdb" ] && continue
478                                         mkdir -p "$dstpath"
479                                         echo "$origin" >> $dstpath/$dstdb.raw
480                                         echo "$dstpath/$dstdb" >> ${DBDIR}/stage.loop_list/make_ignored_dependents_lists_unique.tmp
481                                 done < $dbpath/$srcdb
482                         done
483                 done
484         }
485         _program_exec_and_record_completion__operation ()
486         {
487                 local dbrequires_valesc
488                 message_section_title "Inspection of dependents"
489                 dbrequires_valesc=`str_escape_replaceval "${DBDIR}/requires/"`
490                 program_exec_restartable_loop_operation inspect_dependent
491                 for dbtype in dependents ignored_dependents
492                 do
493                         sort -u "${DBDIR}/stage.loop_list/make_${dbtype}_lists_unique.tmp" 2> /dev/null \
494                                 > ${DBDIR}/stage.loop_list/make_${dbtype}_lists_unique || :
495                         sort -u "${DBDIR}/${dbtype}_files.tmp" 2> /dev/null > ${DBDIR}/${dbtype}_files || :
496                         [ -e "${DBDIR}/make_${dbtype}_lists_unique.prev" ] && \
497                                 fileedit_manipulate_old_lines "${DBDIR}/${dbtype}_files.prev" "${DBDIR}/${dbtype}_files" \
498                                 | xargs rm -f
499                 done
500                 message_echo
501         }
502         program_exec_and_record_completion INSPECT_DEPENDENTS
503 }
504
505 # ============= Restore escaped obsolete packages for inspection =============
506 command_do_restore_escaped_obsoletes ()
507 {
508         local PROGRAM_DEPENDS
509         PROGRAM_DEPENDS='INSPECT_DEPENDENTS'
510         _program_exec_and_record_completion__operation ()
511         {
512                 message_section_title "Restoring escaped obsolete packages for inspection"
513                 cat "${DBDIR}/escaped_obsoletes" 2> /dev/null | database_build_restore
514                 rm -f "${DBDIR}/escaped_obsoletes"
515                 message_echo
516         }
517         program_exec_and_record_completion RESTORE_ESCAPED_OBSOLETE_PACKAGES_FOR_INSPECTION
518 }
519
520 # ============= Remove duplicated lines in dependents lists =============
521 command_do_remove_duplicated_lines_in_dependents_lists ()
522 {
523         local PROGRAM_DEPENDS
524         PROGRAM_DEPENDS='CONVERT_REQUIREMENTS_LIST INSPECT_DEPENDENTS'
525         _program_exec_restartable_loop_operation__routine ()
526         {
527                 local dbpath tag level dstdb
528                 dstdb=$1
529                 cat "$dstdb" "$dstdb.raw" 2> /dev/null | sort -u > $dstdb.tmp
530                 mv "$dstdb.tmp" "$dstdb"
531                 rm -f "$dstdb.raw"
532         }
533         _program_exec_and_record_completion__operation ()
534         {
535                 local dbrequires_valesc
536                 message_section_title "Removing duplicated items in dependents lists"
537                 program_exec_restartable_loop_operation make_dependents_lists_unique
538                 message_echo
539         }
540         program_exec_and_record_completion MAKE_DEPENDENTS_LISTS_UNIQUE
541 }
542
543 # ============= Remove duplicated lines in ignored dependents lists =============
544 command_do_remove_duplicated_lines_in_ignored_dependents_lists ()
545 {
546         local PROGRAM_DEPENDS
547         PROGRAM_DEPENDS='CONVERT_REQUIREMENTS_LIST INSPECT_DEPENDENTS'
548         _program_exec_restartable_loop_operation__routine ()
549         {
550                 local dbpath tag level dstdb
551                 dstdb=$1
552                 cat "$dstdb" "$dstdb.raw" 2> /dev/null | sort -u > $dstdb.tmp
553                 mv "$dstdb.tmp" "$dstdb"
554                 rm -f "$dstdb.raw"
555         }
556         _program_exec_and_record_completion__operation ()
557         {
558                 local dbrequires_valesc
559                 message_section_title "Removing duplicated items in ignored dependents lists"
560                 program_exec_restartable_loop_operation make_ignored_dependents_lists_unique
561                 message_echo
562         }
563         program_exec_and_record_completion MAKE_IGNORED_DEPENDENTS_LISTS_UNIQUE
564 }
565
566 # ============= Preparation of target attribute information =============
567 command_do_preparation_of_target_attribute_information ()
568 {
569         local PROGRAM_DEPENDS _TARGET_ATTR_INFO_table
570         for _TARGET_ATTR_INFO_table in requirements dependents itself
571         do
572                 [ `cat "${DBDIR}/stage.loop_list/target_${_TARGET_ATTR_INFO_table}.replaced.specified" 2> /dev/null \
573                         | wc -l` -gt 0 ] || continue
574                 PROGRAM_DEPENDS='DETERMINE_SPECIFIED_TARGETS CONVERT_REQUIREMENTS_LIST'
575                 _program_exec_restartable_loop_operation__routine ()
576                 {
577                         local origin dbtargets_valesc table
578                         origin=$1
579                         dbtargets_valesc=`str_escape_replaceval "${DBDIR}/targets/"`
580                         table=${_TARGET_ATTR_INFO_table}
581                         for database in requires initial
582                         do
583                                 dbpath=${DBDIR}/$database/$origin
584                                 dstpath=${DBDIR}/targets/$origin
585                                 mkdir -p "$dstpath"
586                                 touch "$dstpath/target_itself"
587                                 echo "$origin" >> ${DBDIR}/all_targets.lst
588                                 [ $table = itself ] && continue
589                                 for tag in all run build
590                                 do
591                                         for level in direct full
592                                         do
593                                                 srcdb=${table}.${tag}.${level}
594                                                 dstdb=target_${database}_${table}.${tag}.${level}
595                                                 [ -e "$dbpath/$srcdb" ] || continue
596                                                 cat "$dbpath/$srcdb" >> ${DBDIR}/all_targets.lst
597                                                 sed -E "s/^/$dbtargets_valesc/; s|$|/$dstdb|" "$dbpath/$srcdb" \
598                                                         | fileedit_add_a_line_to_files_if_new "$origin"
599                                         done
600                                 done
601                         done
602                 }
603                 _program_exec_and_record_completion__operation ()
604                 {
605                         local table
606                         table=${_TARGET_ATTR_INFO_table}
607                         message_section_title "Preparation of target attribute information for dependency [$table]"
608                         program_exec_restartable_loop_operation target_$table.replaced.specified
609                         message_echo
610                 }
611                 program_exec_and_record_completion TARGET_ATTR_INFO:${_TARGET_ATTR_INFO_table}
612         done
613 }
614
615 # ============= Post-process after the preparation of target attribute information =============
616 command_do_post_process_after_the_preparation_of_target_attribute_information ()
617 {
618         local PROGRAM_DEPENDS
619         PROGRAM_DEPENDS='MAKE_DEPENDENTS_LISTS_UNIQUE MAKE_IGNORED_DEPENDENTS_LISTS_UNIQUE TARGET_ATTR_INFO:requirements TARGET_ATTR_INFO:dependents'
620         _program_exec_and_record_completion__operation ()
621         {
622                 message_section_title "Post-process after the preparation of target attribute information"
623                 sort -u "${DBDIR}/all_targets.lst" 2> /dev/null \
624                         | grep -Fx -f "${DBDIR}/inspected_ports" \
625                         | sed -E -f "${DBDIR}/REPLACE.complete_sed_pattern" 2> /dev/null \
626                         > ${DBDIR}/all_targets.lst.tmp || :
627                 mv "${DBDIR}/all_targets.lst.tmp" "${DBDIR}/all_targets.lst"
628                 find "${DBDIR}/targets" -depth 2 -type d > ${DBDIR}/stage.loop_list/build_complement_to_new_dependents_for_targets 2> /dev/null || :
629                 {
630                         cat "${DBDIR}/all_targets.lst" "${DBDIR}/need.with_replaced.list" 2> /dev/null || :
631                         find "${DBDIR}/moved_from" -depth 3 -type f -name installed_version \
632                                 | sed -E 's|.*/([^/]+/[^/]+)/[^/]*$|\1|'
633                 } | sort -u > ${DBDIR}/stage.loop_list/inspect_necessity
634                 cp /dev/null "${DBDIR}/stage.loop_list/parse_target_attr_info"
635                 find -E "${DBDIR}/requires" -depth 3 -type f -regex '.*/necessary_port\.(direct|full)$' -delete
636                 message_echo
637         }
638         program_exec_and_record_completion TARGET_ATTR_INFO_POSTPROCESS
639 }
640
641 # ============= Build of data on complement to new dependents for target attribute information =============
642 command_do_build_of_data_on_complement_to_new_dependents_for_target_attribute_information ()
643 {
644         local PROGRAM_DEPENDS
645         PROGRAM_DEPENDS='TARGET_ATTR_INFO_POSTPROCESS TARGET_ATTR_INFO:requirements TARGET_ATTR_INFO:dependents CONVERT_REQUIREMENTS_LIST'
646         _program_exec_restartable_loop_operation__routine ()
647         {
648                 local dbpath origin
649                 dbpath=$1
650                 origin=`str_dirpath_to_origin "$dbpath"`
651                 database_build_complement_to_new_dependents_for_targets "$origin"
652         }
653         _program_exec_and_record_completion__operation ()
654         {
655                 message_section_title "Build of data on complement to new dependents for target attribute information"
656                 program_exec_restartable_loop_operation build_complement_to_new_dependents_for_targets
657                 sort -u "${DBDIR}/stage.loop_list/parse_target_attr_info" > ${DBDIR}/stage.loop_list/parse_target_attr_info.tmp
658                 mv "${DBDIR}/stage.loop_list/parse_target_attr_info.tmp" "${DBDIR}/stage.loop_list/parse_target_attr_info"
659                 message_echo
660         }
661         program_exec_and_record_completion COMPLEMENT_TO_NEW_DEPENDENTS_FOR_TARGET_ATTR_INFO
662 }
663
664 # ============= Parse target attribute information =============
665 command_do_parse_target_attribute_information ()
666 {
667         local PROGRAM_DEPENDS
668         PROGRAM_DEPENDS='COMPLEMENT_TO_NEW_DEPENDENTS_FOR_TARGET_ATTR_INFO'
669         _program_exec_restartable_loop_operation__routine ()
670         {
671                 local dbpath origin
672                 dbpath=$1
673                 origin=`str_dirpath_to_origin "$dbpath"`
674                 database_build_target_attributes "$origin"
675         }
676         _program_exec_and_record_completion__operation ()
677         {
678                 message_section_title "Parsing target attribute information"
679                 program_exec_restartable_loop_operation parse_target_attr_info
680                 message_echo
681         }
682         program_exec_and_record_completion PARSE_TARGET_ATTR_INFO
683 }
684
685 # ============= Inspection of necessity =============
686 command_do_inspection_of_necessity ()
687 {
688         local PROGRAM_DEPENDS
689         PROGRAM_DEPENDS='TARGET_ATTR_INFO_POSTPROCESS RECURSIVE_REQUIREMENT_LISTS:run RECURSIVE_REQUIREMENT_LISTS:build INSPECT_ALL_DEPENDENCIES'
690         _program_exec_restartable_loop_operation__routine ()
691         {
692                 local origin
693                 origin=$1
694                 for level in direct full
695                 do
696                         database_build_inspect_necessity_for_only_new_upgrade "$origin" "$level"
697                 done
698         }
699         _program_exec_and_record_completion__operation ()
700         {
701                 message_section_title "Inspection of necessity"
702                 program_exec_restartable_loop_operation inspect_necessity
703                 for level in direct full
704                 do
705                         find "${DBDIR}/requires" -depth 3 -type f -name "necessary_port.${level}" | \
706                                 sed -E 's|.*/([^/]+/[^/]+)/[^/]*$|\1|' > ${DBDIR}/stage.loop_list/necessary_ports.${level}
707                 done
708                 message_echo
709         }
710         program_exec_and_record_completion INSPECT_NECESSITY
711 }
712
713 # ============= Inspection of necessary upgrades =============
714 command_do_inspection_of_necessary_upgrades ()
715 {
716         local PROGRAM_DEPENDS _NECESSARY_UPDATES_level
717         for _NECESSARY_UPDATES_level in direct full
718         do
719                 PROGRAM_DEPENDS='INSPECT_NECESSITY INSPECT_ALL_DEPENDENCIES MAKE_DEPENDENTS_LISTS_UNIQUE MAKE_IGNORED_DEPENDENTS_LISTS_UNIQUE'
720                 _program_exec_restartable_loop_operation__routine ()
721                 {
722                         local markerpath level dbpath origin tag
723                         origin=$1
724                         level=${_NECESSARY_UPDATES_level}
725                         dbpath=${DBDIR}/requires/$origin
726                         database_query_does_a_port_need_update "$origin" || return 0
727                         for tag in all run build none
728                         do
729                                 touch "$dbpath/necessary_upgrade.${tag}.${level}"
730                                 [ -e "$dbpath/dependents.${tag}.${level}" -o "$dbpath/ignored_dependents.${tag}" ] || continue
731                                 cat "$dbpath/dependents.${tag}.${level}" "$dbpath/ignored_dependents.${tag}" 2> /dev/null | \
732                                         while read origin_dependent
733                                         do
734                                                 touch "${DBDIR}/requires/$origin_dependent/necessary_upgrade.${tag}.${level}"
735                                         done
736                         done
737                 }
738                 _program_exec_and_record_completion__operation ()
739                 {
740                         local level
741                         level=${_NECESSARY_UPDATES_level}
742                         message_section_title "Inspection of necessary upgrades at the $level level"
743                         program_exec_restartable_loop_operation necessary_ports.${level}
744                         find "${DBDIR}/requires" -depth 3 -type f -name "necessary_upgrade.run.${level}" | \
745                                 sed -E 's|.*/([^/]+/[^/]+)/[^/]*$|\1|' > ${DBDIR}/stage.loop_list/complete_necessary_ports.${level}
746                         message_echo
747                 }
748                 program_exec_and_record_completion NECESSARY_UPDATES:${_NECESSARY_UPDATES_level}
749         done
750 }
751
752 # ============= Completion of necessary upgrades for build =============
753 command_do_complete_necessary_upgrades_for_build ()
754 {
755         local PROGRAM_DEPENDS _NECESSARY_UPDATES_level
756         for _NECESSARY_UPDATES_level in direct full
757         do
758                 PROGRAM_DEPENDS="INSPECT_NECESSITY NECESSARY_UPDATES:${_NECESSARY_UPDATES_level}"
759                 _program_exec_restartable_loop_operation__routine ()
760                 {
761                         local origin level
762                         origin=$1
763                         level=${_NECESSARY_UPDATES_level}
764                         database_build_complete_necessary_upgrades_for_build "$origin" "$level"
765                 }
766                 _program_exec_and_record_completion__operation ()
767                 {
768                         local level
769                         level=${_NECESSARY_UPDATES_level}
770                         message_section_title "Completion of necessary upgrades for build at the $level level"
771                         program_exec_restartable_loop_operation complete_necessary_ports.${level}
772                         message_echo
773                 }
774                 program_exec_and_record_completion COMPLETE_NECESSARY_UPDATES:${_NECESSARY_UPDATES_level}
775         done
776 }
777
778 # ============= Preparation for inspection of new leaf ports =============
779 command_do_preparation_for_inspection_of_new_leaf_ports ()
780 {
781         local PROGRAM_DEPENDS
782         if [ ! -e "${DBDIR}/inspected_ports_only_partially" ]
783         then
784                 PROGRAM_DEPENDS='INSPECT_ALL_DEPENDENCIES MAKE_DEPENDENTS_LISTS_UNIQUE MAKE_IGNORED_DEPENDENTS_LISTS_UNIQUE PARSE_CONF'
785                 _program_exec_and_record_completion__operation ()
786                 {
787                         message_section_title "Preparation for inspection of new leaf ports"
788                         find "${DBDIR}/requires" -depth 3 -type f -name dependents.all.full -or -name ignored_dependents.all \
789                                 | sed -E 's|.*/([^/]+/[^/]+)/[^/]+$|\1|' \
790                                 | sort -u > ${TMPDIR}/PREPARE_INSPECT_LEAF_PORTS:nonleaf_ports
791                         sort -u "${DBDIR}/inspected_ports" > ${TMPDIR}/PREPARE_INSPECT_LEAF_PORTS:inspected_ports
792                         fileedit_manipulate_new_lines \
793                                 "${TMPDIR}/PREPARE_INSPECT_LEAF_PORTS:nonleaf_ports" \
794                                 "${TMPDIR}/PREPARE_INSPECT_LEAF_PORTS:inspected_ports" \
795                                 | grep -v -Fx -f "${DBDIR}/conf/HOLD:PORTS.parsed" 2> /dev/null \
796                                 > ${DBDIR}/stage.loop_list/leaf_ports_primary_candidates || :
797                         cp /dev/null "${DBDIR}/leaf_ports.filter"
798                         cp /dev/null "${DBDIR}/stage.loop_list/leaf_ports_secondary_candidates"
799                         message_echo
800                 }
801                 program_exec_and_record_completion PREPARE_INSPECT_LEAF_PORTS
802         fi
803 }
804
805 # ============= Inspection of new primary leaf ports =============
806 command_do_inspection_of_new_primary_leaf_ports ()
807 {
808         local PROGRAM_DEPENDS
809         if [ ! -e "${DBDIR}/inspected_ports_only_partially" ]
810         then
811                 PROGRAM_DEPENDS='INSPECT_ALL_DEPENDENCIES MAKE_DEPENDENTS_LISTS_UNIQUE MAKE_IGNORED_DEPENDENTS_LISTS_UNIQUE PREPARE_INSPECT_LEAF_PORTS PARSE_CONF'
812                 _program_exec_restartable_loop_operation__routine ()
813                 {
814                         local origin origin_ini dbpath origin_req
815                         origin=$1
816                         pkgsys_is_pkgtool "$origin" && return
817                         dbpath=${DBDIR}/requires/$origin
818                         grep -q -Fx "$origin" "${DBDIR}/need.with_replaced.list" 2> /dev/null && return
819                         if ! grep -q -Fx "$origin" "${DBDIR}/noneed.list" 2> /dev/null
820                         then
821                                 if [ -e "$dbpath/initial_orig" ]
822                                 then
823                                         origin_ini=`cat "$dbpath/initial_orig"`
824                                         [ -e "${DBDIR}/initial/$origin_ini/installed_version" \
825                                                 -a `cat "${DBDIR}/initial/$origin_ini/dependents.all.full" 2> /dev/null | wc -l` -eq 0 ] \
826                                                 && return
827                                 fi
828                                 [ -e "${DBDIR}/initial/$origin/installed_version" \
829                                         -a `cat "${DBDIR}/initial/$origin/dependents.all.full" 2> /dev/null | wc -l` -eq 0 ] \
830                                         && return
831                         fi
832                         if [ -e "$dbpath/requirements.all.full" -o -e "$dbpath/ignored_requirements.all" ]
833                         then
834                                 cat "$dbpath/requirements.all.full" "$dbpath/ignored_requirements.all" 2> /dev/null | \
835                                         grep -v -Fx -f "${DBDIR}/conf/HOLD:PORTS.parsed" 2> /dev/null| \
836                                         fileedit_add_lines_if_new "${DBDIR}/stage.loop_list/leaf_ports_secondary_candidates" || :
837                         fi
838                         fileedit_add_a_line_if_new "$origin" "${DBDIR}/leaf_ports.filter"
839                 }
840                 _program_exec_and_record_completion__operation ()
841                 {
842                         local num_leaves num_leaves_prev
843                         message_section_title "Inspection of new primary leaf ports"
844                         program_exec_restartable_loop_operation leaf_ports_primary_candidates
845                         wc -l < ${DBDIR}/leaf_ports.filter | tr -d ' ' > ${DBDIR}/num_leaves
846                         cp /dev/null "${DBDIR}/leaf_ports_secondary_candidates.new_requirements"
847                         message_echo "  `cat "${DBDIR}/num_leaves"` primary leaf port(s) is/are found."
848                         message_echo
849                 }
850                 program_exec_and_record_completion INSPECT_PRIMARY_LEAF_PORTS
851         fi
852 }
853
854 # ============= Inspection of requirements of new leaf ports =============
855 command_do_inspection_of_requirements_of_new_leaf_ports ()
856 {
857         local PROGRAM_DEPENDS
858         if [ ! -e "${DBDIR}/inspected_ports_only_partially" ]
859         then
860                 PROGRAM_DEPENDS='INSPECT_ALL_DEPENDENCIES MAKE_DEPENDENTS_LISTS_UNIQUE MAKE_IGNORED_DEPENDENTS_LISTS_UNIQUE INSPECT_PRIMARY_LEAF_PORTS PARSE_CONF'
861                 _program_exec_and_record_completion__operation ()
862                 {
863                         local num_leaves num_leaves_prev num_inspect num_leaves_new
864                         message_section_title "Inspection of requirements of new leaf ports"
865                         message_echo "INFO: The inspection proceeds by iterative method."
866                         while :
867                         do
868                                 _program_exec_restartable_loop_operation__routine ()
869                                 {
870                                         local origin dbpath
871                                         origin=$1
872                                         pkgsys_is_pkgtool "$origin" && return
873                                         dbpath=${DBDIR}/requires/$origin
874                                         grep -q -Fx "$origin" "${DBDIR}/need.with_replaced.list" 2> /dev/null && return
875                                         cat "$dbpath/dependents.all.full" "$dbpath/ignored_dependents.all"  2> /dev/null \
876                                                 | grep -Fxq -v -f "${DBDIR}/leaf_ports.filter" 2> /dev/null && return
877                                         cat "$dbpath/requirements.all.full" "$dbpath/ignored_requirements.all" 2> /dev/null \
878                                                 >> ${DBDIR}/leaf_ports_secondary_candidates.new_requirements || :
879                                         fileedit_add_a_line_if_new "$origin" "${DBDIR}/leaf_ports.filter"
880                                 }
881                                 program_exec_restartable_loop_operation leaf_ports_secondary_candidates
882                                 num_leaves_prev=`cat "${DBDIR}/num_leaves"`
883                                 num_leaves=`wc -l < ${DBDIR}/leaf_ports.filter | tr -d ' '`
884                                 num_leaves_new=`echo $(($num_leaves-$num_leaves_prev)) | tr -d ' '`
885                                 if [ $num_leaves_new -eq 0 ]
886                                 then
887                                         message_echo "  No more leaf port is found."
888                                         message_echo "  $num_leaves leaf port(s) is/are found in total."
889                                         break
890                                 fi
891                                 {
892                                         grep -Fx -v -f "${DBDIR}/leaf_ports.filter" \
893                                                 "${DBDIR}/stage.loop_list/leaf_ports_secondary_candidates" || :
894                                         cat "${DBDIR}/leaf_ports_secondary_candidates.new_requirements" || :
895                                 } 2> /dev/null | grep -v -Fx -f "${DBDIR}/conf/HOLD:PORTS.parsed" 2> /dev/null | sort -u \
896                                         > ${DBDIR}/stage.loop_list/leaf_ports_secondary_candidates.tmp || :
897                                 program_reset_loop_for_stage INSPECT_REQUIREMENTS_OF_LEAF_PORTS
898                                 mv "${DBDIR}/stage.loop_list/leaf_ports_secondary_candidates.tmp" \
899                                         "${DBDIR}/stage.loop_list/leaf_ports_secondary_candidates"
900                                 cp /dev/null "${DBDIR}/leaf_ports_secondary_candidates.new_requirements"
901                                 echo "$num_leaves" > ${DBDIR}/num_leaves
902                                 num_inspect=`wc -l < ${DBDIR}/stage.loop_list/leaf_ports_secondary_candidates | tr -d ' '`
903                                 message_echo "  $num_leaves_new leaf port(s) is/are newly found; continue for $num_inspect candidate(s)."
904                         done
905                         grep -Fx -f "${DBDIR}/leaf_ports.filter" "${DBDIR}/inspected_ports" 2> /dev/null | sort -u > ${DBDIR}/leaf_ports || :
906                         message_echo
907                 }
908                 program_exec_and_record_completion INSPECT_REQUIREMENTS_OF_LEAF_PORTS
909         fi
910 }
911
912 # ============= Order the ports considering dependencies =============
913 command_do_order_the_ports_considering_dependencies ()
914 {
915         local PROGRAM_DEPENDS
916         PROGRAM_DEPENDS='CONVERT_REQUIREMENTS_LIST'
917         _program_exec_and_record_completion__operation ()
918         {
919                 message_section_title "Ordering dependencies"
920                 if ! database_build_order_ports_considering_dependencies
921                 then
922                         message_echo "ERROR: Unsatisfied dependencies are remained:" >&2
923                         message_cat "${DBDIR}/unsatisfied.list"
924                         message_echo "*** Aborted by ${APPNAME}"
925                         message_echo "The ports tree seems broken. You might have caught an incomplete version."
926                         message_echo "You are encouraged to update the ports tree by portsnap(8)."
927                         message_echo "Then execute"
928                         message_echo " ${APPNAME} clean"
929                         message_echo "before restart."
930                         temp_terminate_process () { :; }
931                         exit 1
932                 fi
933                 message_echo
934         }
935         program_exec_and_record_completion ORDER_ALL_DEPENDENCIES
936 }
937
938 # ============= Selection of removing leaf ports =============
939 command_do_selection_of_removing_leaf_ports ()
940 {
941         local PROGRAM_DEPENDS
942         PROGRAM_DEPENDS='INSPECT_REQUIREMENTS_OF_LEAF_PORTS'
943         _program_exec_and_record_completion__operation ()
944         {
945                 message_section_title "Selection of removing leaf ports"
946                 deinstall_select_leaf_ports_to_delete
947                 message_echo
948         }
949         program_exec_and_record_completion SELECT_LEAF_PORTS
950 }
951
952 # ============= Selection of removing obsolete ports =============
953 command_do_selection_of_removing_obsolete_ports ()
954 {
955         local PROGRAM_DEPENDS
956         PROGRAM_DEPENDS='INSPECT_ALL_DEPENDENCIES PARSE_CONF'
957         _program_exec_and_record_completion__operation ()
958         {
959                 message_section_title "Selection of removing obsolete ports"
960                 deinstall_select_obsolete_ports_to_delete
961                 message_echo
962         }
963         program_exec_and_record_completion SELECT_OBSOLETE_PORTS
964 }
965
966 # ============= Collection of leaf ports to delete =============
967 command_do_collection_of_leaf_ports_to_delete ()
968 {
969         local PROGRAM_DEPENDS
970         if [ ! -e "${DBDIR}/inspected_ports_only_partially" ]
971         then
972                 PROGRAM_DEPENDS='SELECT_LEAF_PORTS'
973                 _program_exec_and_record_completion__operation ()
974                 {
975                         local src src_unselected reqptn_file src_with_initial_origins
976                         message_section_title "Collecting leaf ports to delete"
977                         src=${DBDIR}/leaf_ports
978                         src_unselected=${DBDIR}/leaf_ports_to_delete.unselected
979                         src_with_initial_origins=${DBDIR}/leaf_ports.with_ini
980                         reqptn_file=${DBDIR}/leaf_ports.requirements_of_unselected
981                         cat "$src_unselected" 2> /dev/null | while read origin
982                         do
983                                 cat "${DBDIR}/requires/$origin/requirements.all.full" "${DBDIR}/requires/$origin/ignored_requirements.all" || :
984                         done 2> /dev/null | sort -u > $reqptn_file
985                         database_query_add_initial_origins < $src > $src_with_initial_origins
986                         message_echo
987                 }
988                 program_exec_and_record_completion COLLECT_LEAF_PORTS_TO_DELETE
989         fi
990 }
991
992 # ============= Collection of obsolete ports to delete =============
993 command_do_collection_of_obsolete_ports_to_delete ()
994 {
995         local PROGRAM_DEPENDS
996         PROGRAM_DEPENDS='SELECT_OBSOLETE_PORTS'
997         _program_exec_and_record_completion__operation ()
998         {
999                 local src src_selected src_unselected dst_selected reqptn_file
1000                 message_section_title "Collecting obsolete ports to delete"
1001                 src=${DBDIR}/obsolete_ports.can_be_deleted
1002                 src_selected=${DBDIR}/obsolete_ports_to_delete.selected
1003                 src_unselected=${DBDIR}/obsolete_ports_to_delete.unselected
1004                 dst_selected=${DBDIR}/obsolete_ports_to_delete
1005                 reqptn_file=${DBDIR}/obsolete_ports.requirements_of_unselected
1006                 cat "$src_unselected" 2> /dev/null | while read origin
1007                 do
1008                         cat "${DBDIR}/initial/$origin/requirements.run.full" || :
1009                         cat "${DBDIR}/obsolete/$origin/requirements.run.full" || :
1010                 done | sort -u > $reqptn_file
1011                 grep -v -Fx -f "$reqptn_file" "$src_selected" > $dst_selected 2> /dev/null || :
1012                 message_echo
1013         }
1014         program_exec_and_record_completion COLLECT_OBSOLETE_PORTS_TO_DELETE
1015 }
1016
1017 # ============= Set up the list of ports to reinstall =============
1018 command_do_set_up_the_list_of_ports_to_reinstall ()
1019 {
1020         local PROGRAM_DEPENDS
1021         PROGRAM_DEPENDS='ORDER_ALL_DEPENDENCIES'
1022         _program_exec_and_record_completion__operation ()
1023         {
1024                 message_section_title "Setting up the list of ports to reinstall"
1025                 cp -p "${DBDIR}/reinst_order.list" "${DBDIR}/stage.loop_list/reinst_todo"
1026                 message_echo
1027         }
1028         program_exec_and_record_completion SETUP_REINST_TODO
1029 }
1030
1031 # ============= Composition of a list for deinstallation of obsolete and leaf packages =============
1032 command_do_composition_of_a_list_for_deinstallation_of_obsolete_and_leaf_packages ()
1033 {
1034         local PROGRAM_DEPENDS
1035         PROGRAM_DEPENDS='COLLECT_LEAF_PORTS_TO_DELETE COLLECT_OBSOLETE_PORTS_TO_DELETE'
1036         _program_exec_and_record_completion__operation ()
1037         {
1038                 local reqptn_leaf reqptn_obs leaf_selected leaf_selected_src obs_selected obs_selected_src grepptn preserved
1039                 message_section_title "Composing a list for deinstallation of obsolete and leaf packages"
1040                 reqptn_leaf=${DBDIR}/leaf_ports.requirements_of_unselected
1041                 reqptn_obs=${DBDIR}/obsolete_ports.requirements_of_unselected
1042                 leaf_selected_src=${DBDIR}/leaf_ports_to_delete.selected
1043                 leaf_selected=${DBDIR}/leaf_ports_to_delete
1044                 obs_selected_src=${DBDIR}/obsolete_ports_to_delete.selected
1045                 obs_selected=${DBDIR}/obsolete_ports_to_delete
1046                 grepptn=${DBDIR}/ports_to_delete.grep_pattern
1047                 grepptn_col1=${DBDIR}/ports_to_delete.grep_pattern_col1
1048                 preserved=${TMPDIR}/LIST_DEINST_PKGS::preserved
1049                 if [ ! -e "${DBDIR}/inspected_ports_only_partially" ]
1050                 then
1051                         cat "$reqptn_leaf" "$reqptn_obs" 2> /dev/null | sort -u > $grepptn
1052                         grep -v -Fx -f "$grepptn" "$leaf_selected_src" 2> /dev/null \
1053                                 | database_query_add_initial_origins > $leaf_selected || :
1054                         cat "$obs_selected" "$leaf_selected" 2> /dev/null || :
1055                 else
1056                         rm -f "$leaf_selected"
1057                         cat "$obs_selected" 2> /dev/null
1058                 fi | sort -u > ${DBDIR}/stage.loop_list/ports_to_delete
1059                 str_escape_regexp_filter < ${DBDIR}/stage.loop_list/ports_to_delete \
1060                         | sed 's/^/^/;s/$/[[:space:]]/' > $grepptn_col1
1061                 cat "${DBDIR}/leaf_ports.with_ini" "${DBDIR}/obsolete_ports" 2> /dev/null \
1062                         | grep -Fx -v -f "${DBDIR}/stage.loop_list/ports_to_delete" > ${DBDIR}/stage.loop_list/ports_to_restore 2> /dev/null || :
1063                 if [ $opt_batch_mode = no ]
1064                 then
1065                         if [ ! -e "${DBDIR}/inspected_ports_only_partially" ] && \
1066                                 grep -v -Fx -f "${DBDIR}/stage.loop_list/ports_to_delete" "$leaf_selected_src" > $preserved 2> /dev/null
1067                         then
1068                                 message_echo "INFO: Following leaf ports are preserved because required by other preserved leaf/obsolete ports."
1069                                 message_echo "----------------"
1070                                 while read origin
1071                                 do
1072                                         pkgtag=`cat "${DBDIR}/moved_from/$origin/pkgtag" 2> /dev/null` || :
1073                                         if [ -n "$pkgtag" ]
1074                                         then
1075                                                 echo "$origin" "($pkgtag)"
1076                                         else
1077                                                 echo "$origin"
1078                                         fi
1079                                 done < $preserved
1080                                 message_echo "----------------"
1081                         fi
1082                         if grep -v -Fx -f "${DBDIR}/stage.loop_list/ports_to_delete" "$obs_selected_src" > $preserved 2> /dev/null
1083                         then
1084                                 message_echo "INFO: Following obsolete ports are preserved because required by other obsolete ports."
1085                                 message_echo "----------------"
1086                                 while read origin
1087                                 do
1088                                         pkgtag=`cat "${DBDIR}/initial/$origin/installed_version" 2> /dev/null` || :
1089                                         if [ -n "$pkgtag" ]
1090                                         then
1091                                                 echo "$origin" "($pkgtag)"
1092                                         else
1093                                                 echo "$origin"
1094                                         fi
1095                                 done < $preserved
1096                                 message_echo "----------------"
1097                         fi
1098                 fi
1099                 message_echo
1100         }
1101         program_exec_and_record_completion LIST_DEINST_PKGS
1102 }
1103
1104 # ============= Collect entire distfiles list =============
1105 command_do_collect_entire_distfiles_list ()
1106 {
1107         local PROGRAM_DEPENDS
1108         if [ $opt_inspect_entire_distinfo = yes ]
1109         then
1110                 PROGRAM_DEPENDS=''
1111                 _program_exec_and_record_completion__operation ()
1112                 {
1113                         message_section_title "Collecting entire distfiles list"
1114                         find "${PORTSDIR}" -depth 3 -name distinfo -exec cat {} \; \
1115                                 | grep '^SHA256 ' | sed -E 's/^SHA256 \(([^)]*)\).*/\1/' \
1116                                 | sort -u > ${DBDIR}/distfiles.entire.tmp
1117                         mv "${DBDIR}/distfiles.entire.tmp" "${DBDIR}/distfiles.entire"
1118                         message_echo
1119                 }
1120                 program_exec_and_record_completion COLLECT_ALL_DISTFILES_LIST
1121         fi
1122 }
1123
1124 # ============= Inspection of all required distfiles =============
1125 command_do_inspection_of_all_required_distfiles ()
1126 {
1127         local PROGRAM_DEPENDS
1128         PROGRAM_DEPENDS='INSPECT_ALL_DEPENDENCIES COLLECT_ALL_DISTFILES_LIST'
1129         _program_exec_and_record_completion__operation ()
1130         {
1131                 message_section_title "Summarizing distfiles list"
1132                 {
1133                         cat "${DBDIR}/distfiles.entire" || :
1134                         cat "${DBDIR}/distfiles.inspected" || :
1135                 } 2> /dev/null | sort -u | str_escape_regexp_filter \
1136                         | sed 's|^|^\\.\\/|; s|$|$|' > ${DBDIR}/distfiles.grep.pattern || :
1137                 message_echo
1138         }
1139         program_exec_and_record_completion DISTFILES_LIST
1140 }
1141
1142 # ============= Clean up of reinstallation status for preparation =============
1143 command_do_clean_up_of_reinstallation_status_for_preparation ()
1144 {
1145         local PROGRAM_DEPENDS
1146         PROGRAM_DEPENDS='REDO_INIT INSPECT_ALL_DEPENDENCIES'
1147         _program_exec_and_record_completion__operation ()
1148         {
1149                 message_section_title "Cleaning up of reinstallation status for preparation"
1150                 rm -rf "${DBDIR}/status.ports"
1151                 message_echo
1152         }
1153         program_exec_and_record_completion CLEANUP_REINST_STATUS
1154 }
1155
1156 # ============= Completion of building the temporary database =============
1157 command_do_completion_of_building_the_temporary_database ()
1158 {
1159         local PROGRAM_DEPENDS
1160         PROGRAM_DEPENDS='REDO_INIT SETUP_REINST_TODO CLEANUP_REINST_STATUS PARSE_CONF INSPECT_ALL_DEPENDENCIES RESTORE_ESCAPED_OBSOLETE_PACKAGES_FOR_INSPECTION NECESSARY_UPDATES:direct NECESSARY_UPDATES:full PARSE_TARGET_ATTR_INFO MAKE_DEPENDENTS_LISTS_UNIQUE MAKE_IGNORED_DEPENDENTS_LISTS_UNIQUE COLLECT_LEAF_PORTS_TO_DELETE'
1161         _program_exec_and_record_completion__operation ()
1162         {
1163                 message_section_title "The temporary database is completely built up"
1164                 message_echo
1165         }
1166         program_exec_and_record_completion PREPARATION
1167 }
1168
1169 # ============= End of do/redo prepare  =============
1170 command_do_end_at_prepare_complete ()
1171 {
1172         local tmp_msg
1173         tmp_msg=${TMPDIR}/command_do_end_at_prepare_complete:msg
1174         cat > "$tmp_msg" << eof
1175 Done (skipped reinstallation) at `message_timestamp`
1176
1177  You can restart this process from the aborted/terminated point by executing without options or arguments as:
1178   ${APPNAME}
1179 eof
1180         message_cat "$tmp_msg"
1181         temp_terminate_process () { :; }
1182 }
1183
1184 # ============= Reinstallation of remained ports =============
1185 command_do_reinstallation_of_remained_ports ()
1186 {
1187         local PROGRAM_DEPENDS
1188         PROGRAM_DEPENDS='PREPARATION'
1189         _program_exec_restartable_loop_operation__routine ()
1190         {
1191                 reinstall_exec "$@"
1192                 temp_set_msg_current_stage "${_MSG_CURRENT_STAGE_general}"
1193         }
1194         _program_exec_and_record_completion__operation ()
1195         {
1196                 local _MSG_CURRENT_STAGE_general
1197                 _MSG_CURRENT_STAGE_general="reinstallation"
1198                 temp_set_msg_current_stage "${_MSG_CURRENT_STAGE_general}"
1199                 message_section_title "Reinstallation"
1200                 program_exec_restartable_loop_operation reinst_todo
1201                 [ "x$PROGRAM_STEP_COUNTER_LAST_SKIPPED" = xyes ] && message_stage_title "$PROGRAM_STEP_COUNTER"
1202                 reinstall_restore_conflicts
1203                 temp_set_msg_current_stage
1204                 message_echo
1205         }
1206         program_exec_and_record_completion REINSTALLATION
1207 }
1208
1209 # ============= Restoration of obsolete and leaf packages which have been deinstalled but unselected from the deletion list again  =============
1210 command_do_restore_needed_obsolete_and_leaf_packages ()
1211 {
1212         local PROGRAM_DEPENDS
1213         PROGRAM_DEPENDS='REDO_INIT LIST_DEINST_PKGS'
1214         _program_exec_restartable_loop_operation__routine ()
1215         {
1216                 deinstall_restore "$@"
1217         }
1218         _program_exec_and_record_completion__operation ()
1219         {
1220                 local _MSG_CURRENT_STAGE_general
1221                 _MSG_CURRENT_STAGE_general="restoration of unselected obsolete/leaf packages"
1222                 temp_set_msg_current_stage "${_MSG_CURRENT_STAGE_general}"
1223                 message_section_title "Restoration of unselected obsolete/leaf packages"
1224                 program_exec_restartable_loop_operation ports_to_restore
1225                 [ "x$PROGRAM_STEP_COUNTER_LAST_SKIPPED" = xyes ] && message_stage_title "$PROGRAM_STEP_COUNTER"
1226                 temp_set_msg_current_stage
1227                 message_echo
1228         }
1229         program_exec_and_record_completion RESTORE_ONCE_DEINST_PKGS
1230 }
1231
1232 # ============= Deinstallation of unused obsolete and leaf packages =============
1233 command_do_deinstallation_of_unused_obsolete_and_leaf_packages ()
1234 {
1235         local PROGRAM_DEPENDS
1236         PROGRAM_DEPENDS='REDO_INIT LIST_DEINST_PKGS'
1237         _program_exec_restartable_loop_operation__routine ()
1238         {
1239                 deinstall_exec "$@"
1240         }
1241         _program_exec_and_record_completion__operation ()
1242         {
1243                 local _MSG_CURRENT_STAGE_general
1244                 _MSG_CURRENT_STAGE_general="deinstallation of obsolete/leaf packages"
1245                 temp_set_msg_current_stage "${_MSG_CURRENT_STAGE_general}"
1246                 message_section_title "Deinstallation of unused obsolete/leaf packages"
1247                 program_exec_restartable_loop_operation ports_to_delete
1248                 [ "x$PROGRAM_STEP_COUNTER_LAST_SKIPPED" = xyes ] && message_stage_title "$PROGRAM_STEP_COUNTER"
1249                 temp_set_msg_current_stage
1250                 message_echo
1251         }
1252         program_exec_and_record_completion DEINST_UNUSED_PKGS
1253 }
1254
1255 # ============= Clean up obsolete or unused distfiles =============
1256 command_do_clean_up_obsolete_or_unused_distfiles ()
1257 {
1258         local PROGRAM_DEPENDS
1259         if [ $opt_only_target_scope = no -a $opt_keep_distfiles = no ]
1260         then
1261                 PROGRAM_DEPENDS='REINSTALLATION DISTFILES_LIST'
1262                 _program_exec_and_record_completion__operation ()
1263                 {
1264                         local tmp_distfiles_exists
1265                         message_section_title "Cleaning up obsolete or unused distfiles"
1266                         tmp_distfiles_exists=${TMPDIR}/CLEANUP_OBSLETE_DISTFILES::distfiles_exists
1267                         [ $opt_dry_run = yes ] && message_echo "INFO: The operations are not actually carried out."
1268                         ( set -e; cd "${DISTDIR}" && find . -type f ) \
1269                                 | sed 's|^\./||' | sort -u > $tmp_distfiles_exists
1270                         fileedit_manipulate_old_lines "$tmp_distfiles_exists" "${DBDIR}/distfiles.entire" \
1271                                 | while read distfile
1272                         do
1273                                 if [ $opt_batch_mode = no ]
1274                                 then
1275                                         echo "  $distfile"
1276                                 fi
1277                                 [ $opt_dry_run = yes ] && continue
1278                                 rm -f "${DISTDIR}/$distfile"
1279                         done
1280                         message_echo
1281                 }
1282                 program_exec_and_record_completion CLEANUP_OBSLETE_DISTFILES
1283         fi
1284 }
1285
1286 # ============= Rebuild of package database =============
1287 command_do_rebuild_of_package_database ()
1288 {
1289         local PROGRAM_DEPENDS
1290         PROGRAM_DEPENDS='REINSTALLATION RESTORE_ONCE_DEINST_PKGS DEINST_UNUSED_PKGS'
1291         _program_exec_and_record_completion__operation ()
1292         {
1293                 which -s pkgdb || return 0
1294                 message_section_title "Rebuilding package database for portupgrade"
1295                 if grep -q @ "${DBDIR}/stage.loop_list/reinst_todo"
1296                 then
1297                         message_echo "INFO: Skipped because of lacking flavor support."
1298                 else
1299                         pkgdb -fu
1300                 fi
1301                 message_echo
1302         }
1303         program_exec_and_record_completion REBUILD_PKGDB
1304 }
1305
1306 # =============Operation of redo command irrespective of option settings =============
1307 command_do_redo__command_all_exec_irrespective_of_saved_options ()
1308 {
1309         [ $opt_reload_conf = yes ] || return 0
1310         program_deregister_stage_complete SAVE_PREV_CONF
1311         program_deregister_stage_complete ALL_COMPLETE
1312         rm -f "${DBDIR}"/complete
1313 }
1314
1315 # ============= Preparation of the temporary database =============
1316 command_do_prepare ()
1317 {
1318         # Meta process for redo
1319         command_do_meta_process_for_redo
1320         
1321         # Determine specified targets
1322         command_do_determine_specified_targets
1323         
1324         # Show specified targets
1325         command_do_show_specified_targets
1326         
1327         # Determine all target ports
1328         command_do_determine_all_target_ports
1329         
1330         # Inspection of all initial dependencies
1331         command_do_inspection_of_all_initial_dependencies
1332         
1333         # Loop considering cases that port options are changed after inspection
1334         while true
1335         do
1336                 # Prepare for inspecting all dependencies
1337                 command_do_prepare_for_inspect_all_dependencies
1338                 
1339                 # Inspection of all dependencies
1340                 command_do_inspection_of_all_dependencies
1341                 
1342                 # Convert dependency-lists to actual ones
1343                 command_do_convert_dependency_lists_to_actual_ones
1344                 
1345                 # Completion of recursive requirement lists
1346                 command_do_completion_of_recursive_requirement_lists
1347                 
1348                 # Trim dependency lists by removing uninspected ports
1349                 command_do_trim_dependency_lists_by_removing_uninspected_ports
1350                 
1351                 # Inspection of dependents
1352                 command_do_inspection_of_dependents
1353                 
1354                 # End the loop when no change is made on port options after the inspection
1355                 command_do_reset_changed_portdb && break
1356         done
1357         
1358         # Restore escaped obsolete packages for inspection
1359         command_do_restore_escaped_obsoletes
1360         
1361         # Remove duplicated lines in dependents lists
1362         command_do_remove_duplicated_lines_in_dependents_lists
1363         
1364         # Remove duplicated lines in ignored dependents lists
1365         command_do_remove_duplicated_lines_in_ignored_dependents_lists
1366         
1367         # Preparation of target attribute information
1368         command_do_preparation_of_target_attribute_information
1369         
1370         # Post-process after the preparation of target attribute information
1371         command_do_post_process_after_the_preparation_of_target_attribute_information
1372         
1373         # Build of data on complement to new dependents for target attribute information
1374         command_do_build_of_data_on_complement_to_new_dependents_for_target_attribute_information
1375         
1376         # Parse target attribute information
1377         command_do_parse_target_attribute_information
1378         
1379         # Inspection of necessity
1380         command_do_inspection_of_necessity
1381         
1382         # Inspection of necessary upgrades
1383         command_do_inspection_of_necessary_upgrades
1384         
1385         # Completion of necessary upgrades for build
1386         command_do_complete_necessary_upgrades_for_build
1387         
1388         # Preparation for inspection of new leaf ports
1389         command_do_preparation_for_inspection_of_new_leaf_ports
1390         
1391         # Inspection of new primary leaf ports
1392         command_do_inspection_of_new_primary_leaf_ports
1393         
1394         # Inspection of requirements of new leaf ports
1395         command_do_inspection_of_requirements_of_new_leaf_ports
1396         
1397         # Order the ports considering dependencies
1398         command_do_order_the_ports_considering_dependencies
1399         
1400         # Selection of removing leaf ports
1401         command_do_selection_of_removing_leaf_ports
1402         
1403         # Selection of removing obsolete ports
1404         command_do_selection_of_removing_obsolete_ports
1405         
1406         # Collection of leaf ports to delete
1407         command_do_collection_of_leaf_ports_to_delete
1408         
1409         # Collection of obsolete ports to delete
1410         command_do_collection_of_obsolete_ports_to_delete
1411         
1412         # Set up the list of ports to reinstall
1413         command_do_set_up_the_list_of_ports_to_reinstall
1414         
1415         # Composition of a list for deinstallation of obsolete and leaf packages
1416         command_do_composition_of_a_list_for_deinstallation_of_obsolete_and_leaf_packages
1417         
1418         # Collect entire distfiles list
1419         command_do_collect_entire_distfiles_list
1420         
1421         # Inspection of all required distfiles
1422         command_do_inspection_of_all_required_distfiles
1423         
1424         # Clean up of reinstallation status for preparation
1425         command_do_clean_up_of_reinstallation_status_for_preparation
1426         
1427         # Completion of building the temporary database
1428         command_do_completion_of_building_the_temporary_database
1429 }
1430
1431 # ============= Reset the progress of reinstallation for retrial =============
1432 command_do_reset_for_reinst_retrial ()
1433 {
1434         program_deregister_stage_complete REINSTALLATION
1435         program_deregister_stage_complete RESTORE_ONCE_DEINST_PKGS
1436         program_deregister_stage_complete DEINST_UNUSED_PKGS
1437         rm -rf "${DBDIR}/status.ports" "${DBDIR}/new_success_in_current_run"
1438 }
1439
1440 # ============= Main operation of do/redo =============
1441 command_do_main ()
1442 {
1443         local ntrial
1444         # Reset termination messages
1445         temp_reset_termination_messages_common
1446         
1447         ntrial=0
1448         while true
1449         do
1450                 if [ $ntrial -gt 0 ]
1451                 then
1452                         message_echo "########## RETRIAL ($ntrial) OF (RE)INSTALLATION ##########"
1453                         message_echo
1454                 fi
1455                 
1456                 if [ $opt_fetch_only = yes ]
1457                 then
1458                         # Reinstallation of remained ports
1459                         command_do_reinstallation_of_remained_ports
1460                         
1461                         message_echo "Completed the fetch only mode."
1462                         exit
1463                 elif [ $opt_delete_then_reinstall = no ]
1464                 then
1465                         # Reinstallation of remained ports
1466                         command_do_reinstallation_of_remained_ports
1467                         
1468                         # Restoration of obsolete and leaf packages which have been deinstalled but unselected from the deletion list again 
1469                         command_do_restore_needed_obsolete_and_leaf_packages
1470                         
1471                         # Deinstallation of unused obsolete and leaf packages
1472                         command_do_deinstallation_of_unused_obsolete_and_leaf_packages
1473                 else
1474                         # Deinstallation of unused obsolete and leaf packages
1475                         command_do_deinstallation_of_unused_obsolete_and_leaf_packages
1476                         
1477                         # Reinstallation of remained ports
1478                         command_do_reinstallation_of_remained_ports
1479                         # Restoration of obsolete and leaf packages which have been deinstalled but unselected from the deletion list again 
1480                         
1481                         command_do_restore_needed_obsolete_and_leaf_packages
1482                 fi
1483                 
1484                 # Clean up obsolete or unused distfiles
1485                 command_do_clean_up_obsolete_or_unused_distfiles
1486                 
1487                 # Rebuild of package database
1488                 command_do_rebuild_of_package_database
1489                 
1490                 # Retry if incomplete
1491                 command_do_is_everything_resolved && break
1492                 database_query_is_any_progress || break
1493                 command_do_reset_for_reinst_retrial
1494                 ntrial=$(($ntrial+1))
1495         done
1496         :
1497 }
1498
1499 # ============= Check whether everything is resolved =============
1500 command_do_is_everything_resolved ()
1501 {
1502         local subject
1503         for subject in failure redo conflict
1504         do
1505                 database_query_show_single_list_exec "$subject" \
1506                         `options_get_dependency_type` `options_get_dependency_level` > /dev/null 2> /dev/null && return 1
1507         done
1508         :
1509 }
1510
1511 # ============= Notice of failures =============
1512 command_do_failure_notice ()
1513 {
1514         local exists_unresolved_ports
1515         exists_unresolved_ports=
1516         message_summary_dependents_of_failed_reinstallation failure || exists_unresolved_ports=y
1517         message_summary_dependents_of_failed_reinstallation redo || exists_unresolved_ports=y
1518         message_summary_dependents_of_failed_reinstallation conflict || exists_unresolved_ports=y
1519         [ "x$exists_unresolved_ports" = xy ] || return 0
1520         message_summary_advice_on_manual_solution
1521         return 1
1522 }
1523
1524 # ============= Ending process =============
1525 command_do_ending_process ()
1526 {
1527         local PROGRAM_DEPENDS
1528         temp_terminate_process () { :; }
1529         if command_do_failure_notice
1530         then
1531                 if [ $opt_no_opening_message = yes ]
1532                 then
1533                         message_echo "Done as ${APPNAME}"
1534                 else
1535                         message_section_title "COMPLETELY DONE"
1536                 fi
1537                 if [ $opt_fetch_only = no -a $opt_dry_run = no ]
1538                 then
1539                         PROGRAM_DEPENDS='REBUILD_PKGDB CLEANUP_OBSLETE_DISTFILES '
1540                         _program_exec_and_record_completion__operation ()
1541                         {
1542                         }
1543                         program_exec_and_record_completion ALL_COMPLETE
1544                         [ $opt_no_opening_message = yes ] || message_echo "- E N D -"
1545                 else
1546                         message_echo "INFO: Redo for the real (re)installation."
1547                 fi
1548         else
1549                 message_warn_no_achieved_progress
1550                 message_section_title "Done with some unresolved problems"
1551                 message_echo "- To be continued -"
1552         fi
1553 }