OSDN Git Service

9e2600317c788955e8dfd59d3373987d14ea42f6
[portsreinstall/current.git] / bin / portsreinstall
1 #!/bin/sh -e
2 # ==================================================================================
3 # portsreinstall main script
4 # Copyright (C) 2010-2013 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
5 # This software is distributed under the 2-Clause BSD License.
6 # ==================================================================================
7
8 # ==================================================
9 # ================== ENVIRONMENT ===================
10 # ==================================================
11
12 # ============ Set up of environment =============
13 APPNAME=`basename "$0"`
14
15 MYVERSION=3.0.4
16 COMPATIBLE_VERSIONS='^(3\.0\.[0-9]+)$'
17 # Template for development versions
18 # MYVERSION=3.0.3+toward_3.0.4_20131115074959
19 # COMPATIBLE_VERSIONS='^(3\.0\.[0-9]+\+toward_3\.0\.[0-9]+_[0-9]+|3\.0\.[0-9]+)$'
20 MYPREFIX=`dirname "\`dirname \"$0\"\`" | sed 's|/bin$||'`
21 MYPREFIX=${MYPREFIX:-/usr/local}
22 LIBDIR=${MYPREFIX}/lib/${APPNAME}
23
24 . ${LIBDIR}/libtemp.sh
25 . ${LIBDIR}/libstr.sh
26 . ${LIBDIR}/liboptions.sh
27 . ${LIBDIR}/libusage.sh
28 . ${LIBDIR}/libmessage.sh
29 . ${LIBDIR}/libpkgsys.sh
30 . ${LIBDIR}/libmisc.sh
31 . ${LIBDIR}/libfileedit.sh
32 . ${LIBDIR}/libconf.sh
33 . ${LIBDIR}/libdatabase_build.sh
34 . ${LIBDIR}/libdatabase_query.sh
35 . ${LIBDIR}/libdatabase_record.sh
36 . ${LIBDIR}/libcommand.sh
37 . ${LIBDIR}/libprogram.sh
38 . ${LIBDIR}/libreinstall.sh
39 . ${LIBDIR}/libdeinstall.sh
40
41 misc_init_vardefs
42 temp_trap_init
43 conf_setup_envs
44 DBDIR=/var/tmp/${APPNAME}.db
45 CONFFILE=${MYPREFIX}/etc/${APPNAME}.conf
46 PKGTOOLSCONF=${MYPREFIX}/etc/pkgtools.conf
47
48
49 # ==================================================
50 # ========= PARSING OPTIONS AND ARGUMENTS ==========
51 # ==================================================
52
53 # ============= Save arguments for upgraded restart =============
54 options_dump_args "$@" > ${TMPDIR}/restart_command.sh
55
56 # ============= Option check =============
57 options_set_default
58
59 options_getopts "$@" || :
60 if [ $OPTIONS_ERRNO -eq 2 ]
61 then
62         message_echo "INTERNAL ERROR: In parsing options" >&2
63         exit 1
64 fi
65 shift "${OPTIONS_SHIFT}"
66
67 # ============= Argument check for no-command options =============
68 if [ $opt_help_mode -ne 0 -o $opt_show_version = yes ]
69 then
70         if [ $# -gt 0 ]
71         then
72                 OPTIONS_ERRNO=1
73         fi
74 fi
75
76 # ============= Output usage if the case of a help mode or option/argument errors =============
77 if [ $OPTIONS_ERRNO -ne 0 ]
78 then
79         exit $OPTIONS_ERRNO
80 elif [ $opt_help_mode -eq 1 ]
81 then
82         usage_short
83         exit
84 elif [ $opt_help_mode -eq 2 ]
85 then
86         usage_long | less
87         exit
88 fi
89
90 # ============= Output version number =============
91 if [ $opt_show_version = yes ]
92 then
93         message_version
94         exit
95 fi
96
97 # ============= Execute command operations before getting the temporary database ready =============
98 command_exec_before_db_creation "$@"
99
100 # ============= Creation of temporary database directory =============
101 database_build_create
102
103 # ============= Argument check for conventional runs =============
104 command_parse_args "$@"
105 shift "${COMMAND_SHIFT}"
106
107
108 # ==================================================
109 # ================== TOOLS SET UP ==================
110 # ==================================================
111
112 # ============= Opening title =============
113
114 message_credit
115 [ $COMMAND_MODE = do -o $COMMAND_MODE = redo -o $COMMAND_MODE = forget ] && \
116         message_opening_notice
117 message_echo
118
119 # ============= Execute command operations which do not need package tools =============
120
121 command_exec_without_pkgtools "$@"
122 misc_is_superuser_privilege && touch "${DBDIR}/in_use"
123
124 # ============= Definition of environment dependent functions =============
125
126 pkgsys_def_pkgtools
127
128 # ============= Option settings =============
129
130 # Execute command operations which are not affected by saved option settings
131 command_exec_irrespective_of_saved_options "$@"
132
133 # Load, renew and save option values
134 optcomb_err=0
135 options_chk_invalid_optvals_renewal non_renewable || optcomb_err=$?
136 if [ \( $opt_reload_conf = yes -o $opt_reset_targets = yes \) -a "x$COMMAND_MODE" != xredo ]
137 then
138         message_echo "ERROR: Option -N is available only in the initial run of redo command." >&2
139         message_echo >&2
140         optcomb_err=1
141 fi
142 if [ $opt_batch_ports_only = yes -a $opt_interactive_ports_only = yes ]
143 then
144         message_echo "ERROR: Options -A and -I conflict with each other." >&2
145         message_echo >&2
146         optcomb_err=1
147 fi
148 if [ -e "${DBDIR}/saved_options.sh" ]
149 then
150         {
151                 options_renewed_optvals M renewable_anytime || optcomb_err=$?
152                 options_renewed_optvals N renewable_in_redo_on_target || optcomb_err=$?
153                 options_renewed_optvals L renewable_in_redo_on_conf || optcomb_err=$?
154         } > ${TMPDIR}/renewed_optvals.sh
155         [ $optcomb_err -eq 0 ] || exit $optcomb_err
156         . "${DBDIR}/saved_options.sh"
157         . "${TMPDIR}/renewed_optvals.sh"
158 fi
159 misc_is_superuser_privilege && misc_get_all_vardefs | options_filter saved > ${DBDIR}/saved_options.sh
160
161 # Show option values
162 if [ -e "${DBDIR}/saved_options.sh" -a $opt_batch_mode = no \
163         -a \( $COMMAND_MODE = do -o $COMMAND_MODE = redo \) ]
164 then
165         message_echo "INFO: List of option values:"
166         message_echo "-----------------------------------------"
167         message_cat "${DBDIR}/saved_options.sh"
168         message_echo "-----------------------------------------"
169         message_echo
170 fi
171
172 # ============= Termination messages during construction of the temporary database =============
173
174 # Set termination messages
175 temp_terminate_process_common ()
176 {
177         local msg_where
178         [ $opt_batch_mode = yes ] && return
179         msg_where=`temp_get_msg_current_stage`
180         [ -n "$msg_where" ] && msg_where=" during $msg_where"
181         echo
182         if [ $errno -eq 130 ]
183         then
184                 echo "INFO: Terminated at `message_timestamp`$msg_where."
185                 echo
186                 echo " You can restart this process from the terminated point by"
187         else
188                 echo "INFO: Aborted at `message_timestamp`$msg_where."
189                 echo
190                 echo " You may restart this process from the aborted point by"
191         fi
192         echo "executing without options or arguments as:"
193         if [ -n "$COMMAND_RESTART" ]
194         then
195                 echo "  ${APPNAME} $COMMAND_RESTART"
196         else
197                 echo "  ${APPNAME}"
198         fi
199 }
200
201 temp_terminate_process ()
202 {
203         [ $errno -eq 0 -o $opt_batch_mode = yes ] && return
204         temp_terminate_process_common
205         [ -n "$COMMAND_RESTART" ] || message_cat 3<< eof
206  Instead, if you only want to construct the temporary database so as to stop before the actual reinstallation, execute as:
207   ${APPNAME} prepare
208 eof
209 }
210
211 # ============= Configurations =============
212
213 # Save the previous configuration if exists
214 PROGRAM_DEPENDS=''
215 _program_exec_and_record_completion__operation ()
216 {
217         rm -rf "${DBDIR}/conf.prev"
218         [ -d "${DBDIR}/conf" ] && \
219                 cp -Rp "${DBDIR}/conf" "${DBDIR}/conf.prev"
220         :
221 }
222 program_exec_and_record_completion SAVE_PREV_CONF
223
224 # Get complete configuration variable definitions by importing pkgtools.conf(5) if available
225 PROGRAM_DEPENDS='SAVE_PREV_CONF'
226 _program_exec_and_record_completion__operation ()
227 {
228         local need_msg
229         need_msg=no
230         rm -rf "${DBDIR}/conf"
231         mkdir -p "${DBDIR}/conf"
232         [ "x`options_get_effective_opt_load_pkgtoolsconf 2> /dev/null`" != xno -a $opt_batch_mode = no ] \
233                 && need_msg=yes
234         [ $need_msg = yes ] && \
235                 message_section_title "Parsing pkgtools.conf (by using installed portupgrade)"
236         conf_get_complete_var_defs > ${DBDIR}/conf/complete_setup.sh
237         [ $need_msg = yes ] &&  { message_echo "===> ok"; message_echo; }
238         :
239 }
240 program_exec_and_record_completion GET_COMPLETE_CONF_VAR_DEF
241
242 # Parse the configuration
243 PROGRAM_DEPENDS='GET_COMPLETE_CONF_VAR_DEF'
244 _program_exec_and_record_completion__operation ()
245 {
246         message_section_title "Parsing the configuration"
247         conf_manipulate_available_var_defs
248         . "${DBDIR}/conf/manipulated_defs.sh"
249         # ALT_MOVED_*
250         conf_build_effective_MOVED
251         # Environmental variables
252         conf_setup_effective_env > ${DBDIR}/conf/setenv.sh
253         . "${DBDIR}/conf/setenv.sh"
254         # HOLD_*
255         conf_parse_vars_for_each_port_glob HOLD
256         str_escape_regexp_filter < ${DBDIR}/conf/HOLD:PORTS.parsed \
257                 | sed 's/^/^/;s/$/$/' > ${DBDIR}/conf/HOLD_PORTS.grep_pattern
258         # TABOO_*
259         conf_parse_vars_for_each_port_glob TABOO
260         fileedit_combine_lists "${DBDIR}/conf/TABOO:PORTS.parsed" "${DBDIR}/taboo.list" \
261                 > ${DBDIR}/taboo.all.list
262         # NOPKG_*
263         conf_parse_vars_for_each_port_glob NOPKG
264         # REPLACE_*
265         conf_build_replacement_patterns_from_REPLACE
266         # MARG_*
267         conf_parse_vars_for_each_port_glob_with_bound_val MARG TARGET DEF
268         # MENV_*
269         conf_parse_vars_for_each_port_glob_with_bound_val MENV TARGET DEF
270         # BEFOREBUILD_*
271         conf_parse_vars_for_each_port_glob_with_bound_val BEFOREBUILD TARGET COMMAND
272         # BEFOREDEINSTALL_*
273         conf_parse_vars_for_each_port_glob_with_bound_val BEFOREDEINSTALL TARGET COMMAND
274         # AFTERINSTALL_*
275         conf_parse_vars_for_each_port_glob_with_bound_val AFTERINSTALL TARGET COMMAND
276         message_echo
277 }
278 program_exec_and_record_completion PARSE_CONF
279
280 . "${DBDIR}/conf/setenv.sh"
281
282 # ============= Upgrade of tools =============
283
284 # Execute command operations which should be done without upgrade of tools
285 command_exec_before_tools_upgrade "$@"
286
287 # Check whether the temporary database is newer than the ports tree and refresh if so
288 database_build_refresh_if_obsolete
289
290 # Get the port origin for this utility if installed by port
291 MYPORTORIGIN=`pkgsys_get_my_origin 2> /dev/null` || :
292
293 # Collect all installed packages
294 PROGRAM_DEPENDS=''
295 _program_exec_and_record_completion__operation ()
296 {
297         message_section_title "Collecting all installed packages"
298         pkg_info_qoa > ${DBDIR}/installed_ports
299         pkg_info_gen_pkg_origin_table
300         str_escape_regexp_filter < "${DBDIR}/installed_ports" \
301                 | sed 's/^/^/; s/$/$/' > ${DBDIR}/installed_ports.grep_pattern
302         message_echo
303 }
304 program_exec_and_record_completion COLLECT_ALL_INSTALLED_PACKAGES
305
306 # Preliminary inspection of tools which have to be up-to-date
307 # (No need depend on PARSE_CONF because INSPECT_ALL_DEPENDENCIES will take the task.)
308 PROGRAM_DEPENDS=
309 _program_exec_restartable_loop_operation__routine ()
310 {
311         local origin
312         origin=$1
313         database_build_inspect_dependencies "$origin"
314 }
315 _program_exec_and_record_completion__operation ()
316 {
317         local DEPTH_INDEX
318         message_section_title "Preliminary inspection of tools which have to be up-to-date"
319         {
320                 [ "$PKGSYS_USE_PKGNG" = yes ] && echo 'ports-mgmt/pkg'
321                 pkgsys_is_dialog4ports_used && echo 'ports-mgmt/dialog4ports'
322                 [ -n "$MYPORTORIGIN" ] && echo "$MYPORTORIGIN"
323         } 2> /dev/null > ${DBDIR}/stage.loop_list/tools_to_inspect
324         DEPTH_INDEX='--'
325         program_exec_restartable_loop_operation tools_to_inspect
326         database_build_post_inspect_dependencies
327         message_echo
328 }
329 program_exec_and_record_completion PRELIMINARY_INSPECTION_OF_TOOLS
330
331 # Upgrade of ports-mgmt/pkg if new
332 # (No need depend on PARSE_CONF because REINSTALLATION will take the task.)
333 if [ \( "$COMMAND_MODE" = do -o "$COMMAND_MODE" = redo \) \
334         -a $opt_dry_run = no -a $opt_suppress_pkgtools_upadte = no \
335         -a "$PKGSYS_USE_PKGNG" = yes ]
336 then
337         PROGRAM_DEPENDS='PRELIMINARY_INSPECTION_OF_TOOLS'
338         _program_exec_and_record_completion__operation ()
339         {
340                 local _MSG_CURRENT_STAGE_general
341                 _MSG_CURRENT_STAGE_general="pkgng upgrade"
342                 temp_set_msg_current_stage "${_MSG_CURRENT_STAGE_general}"
343                 message_section_title "Upgrade of ports-mgmt/pkg if new"
344                 touch "${DBDIR}/target_all"
345                 reinstall_exec ports-mgmt/pkg
346                 reinstall_restore_conflicts
347                 rm -f "${DBDIR}/target_all"
348                 temp_set_msg_current_stage
349                 message_echo
350         }
351         program_exec_and_record_completion UPGRADE_PKGNG
352 fi
353
354 # Upgrade of ports-mgmt/dialog4ports if new
355 # (No need depend on PARSE_CONF because REINSTALLATION will take the task.)
356 if [ \( "$COMMAND_MODE" = do -o "$COMMAND_MODE" = redo \) \
357         -a $opt_dry_run = no -a $opt_suppress_pkgtools_upadte = no ] \
358         && pkgsys_is_dialog4ports_used
359 then
360         PROGRAM_DEPENDS='PRELIMINARY_INSPECTION_OF_TOOLS'
361         _program_exec_and_record_completion__operation ()
362         {
363                 local _MSG_CURRENT_STAGE_general
364                 _MSG_CURRENT_STAGE_general="pkgng dialog4ports"
365                 temp_set_msg_current_stage "${_MSG_CURRENT_STAGE_general}"
366                 message_section_title "Upgrade of dialog4ports if new"
367                 touch "${DBDIR}/target_all"
368                 reinstall_exec ports-mgmt/dialog4ports
369                 reinstall_restore_conflicts
370                 rm -f "${DBDIR}/target_all"
371                 temp_set_msg_current_stage
372                 message_echo
373         }
374         program_exec_and_record_completion UPGRADE_DIALOG4PORTS
375 fi
376
377 # Upgrade of this utility if new
378 # (No need depend on PARSE_CONF because REINSTALLATION will take the task.)
379 if [ \( "$COMMAND_MODE" = do -o "$COMMAND_MODE" = redo \) \
380         -a $opt_dry_run = no -a $opt_suppress_self_upadte = no \
381         -a -n "$MYPORTORIGIN" ]
382 then
383         PROGRAM_DEPENDS='PRELIMINARY_INSPECTION_OF_TOOLS'
384         _program_exec_and_record_completion__operation ()
385         {
386                 local _MSG_CURRENT_STAGE_general
387                 _MSG_CURRENT_STAGE_general="pkgng upgrade"
388                 temp_set_msg_current_stage "${_MSG_CURRENT_STAGE_general}"
389                 message_section_title "Upgrade of this utility if new"
390                 touch "${DBDIR}/target_all"
391                 reinstall_exec "$MYPORTORIGIN"
392                 reinstall_restore_conflicts
393                 rm -f "${DBDIR}/target_all"
394                 temp_set_msg_current_stage
395                 message_echo
396         }
397         program_exec_and_record_completion UPGRADE_SELF
398 fi
399
400 if [ "x`${APPNAME} -aV 2> /dev/null`" != "x$MYVERSION" ]
401 then
402         message_echo "INFO: ${APPNAME} is upgraded and the temporary database needs refresh."
403         database_build_clean_for_self_upgrade || :
404         message_echo "INFO: Restarting with the new version."
405         message_echo
406         temp_trap_for_invoking_new_version
407         . "${TMPDIR}"/restart_command.sh
408         exit
409 fi
410
411
412 # ==================================================
413 # ================== PREPARATION ===================
414 # ==================================================
415
416 # ============= Correspondence to configuration changes =============
417
418 # Patch to the temporary database by reflecting changes in configuration
419 PROGRAM_DEPENDS='PARSE_CONF'
420 _program_exec_and_record_completion__operation ()
421 {
422         local tmpfile_diff tmpfile_old tmpfile_new key
423         [ -d "${DBDIR}/conf.prev" ] || return 0
424         message_section_title "Patch to the temporary database by reflecting changes in configuration"
425         tmpfile_old=${TMPDIR}/PATCH_TO_TMPDB_REFLECT_CONF_CHANGES::old
426         tmpfile_new=${TMPDIR}/PATCH_TO_TMPDB_REFLECT_CONF_CHANGES::new
427         tmpfile_updated_ports=${TMPDIR}/PATCH_TO_TMPDB_REFLECT_CONF_CHANGES::updated_ports
428         if fileedit_manipulate_old_new_lines \
429                 "${DBDIR}/conf.prev/setenv.sh" "${DBDIR}/conf/setenv.sh" "$tmpfile_old" "$tmpfile_new"
430         then
431                 if grep -q -e ^LOCALBASE= -e ^LINUXBASE= -e ^PORTSDIR= "$tmpfile_old" "$tmpfile_new"
432                 then
433                         message_echo "ERROR: Migration of the temporary database is unavailable because LOCALBASE, LINUXBASE or PORTSDIR was changed." >&2
434                         message_echo "        ${APPNAME} clean" >&2
435                         message_echo "must be executed in advance." >&2
436                         exit 1
437                 fi
438         fi
439         cut -s -d '|' -f 1,2 "${DBDIR}/conf.prev/MOVED_ALT.parsed" | tr '|' '\t' > ${TMPDIR}/MOVED_ALT.old
440         cut -s -d '|' -f 1,2 "${DBDIR}/conf/MOVED_ALT.parsed" | tr '|' '\t' > ${TMPDIR}/MOVED_ALT.new
441         if fileedit_manipulate_old_new_lines \
442                 "${TMPDIR}/MOVED_ALT.old" "${TMPDIR}/MOVED_ALT.new" "$tmpfile_old" "$tmpfile_new"
443         then
444                 cat "$tmpfile_old" "$tmpfile_new" | while read from to
445                 do
446                         echo "$from"
447                         [ -n "$to" ] && echo "$to"
448                 done
449         fi > $tmpfile_updated_ports
450         if fileedit_manipulate_old_new_lines \
451                 "${DBDIR}/conf.prev/REPLACE.csv" "${DBDIR}/conf/REPLACE.csv" "$tmpfile_old" "$tmpfile_new"
452         then
453                 cat "$tmpfile_old" "$tmpfile_new" | while read from to
454                 do
455                         echo "$from"
456                         [ -n "$to" ] && echo "$to"
457                 done
458         fi >> $tmpfile_updated_ports
459         [ `wc -l < $tmpfile_updated_ports` -gt 0 ] && rm -f "${DBDIR}/REPLACE.complete_sed_pattern"
460         [ -d "${DBDIR}/conf/each_port" ] && find "${DBDIR}/conf/each_port" -depth 2 \
461                 | while read dbpath
462         do
463                 origin=`str_dirpath_to_origin "$dbpath"`
464                 dbpath_prev=${DBDIR}/conf.prev/each_port/$origin
465                 diff -r "$dbpath_prev" "$dbpath" > /dev/null 2>&1 && continue
466                 echo "$origin"
467         done >> $tmpfile_updated_ports
468         [ -d "${DBDIR}/conf.prev/each_port" ] && find "${DBDIR}/conf.prev/each_port" -depth 2 \
469                 | while read dbpath_prev
470         do
471                 origin=`str_dirpath_to_origin "$dbpath_prev"`
472                 dbpath=${DBDIR}/conf/each_port/$origin
473                 [ -d "$dbpath" ] && continue
474                 echo "$origin"
475         done >> $tmpfile_updated_ports
476         if [ `wc -l < $tmpfile_updated_ports` -gt 0 ]
477         then
478                 sort -u "$tmpfile_updated_ports" | while read origin
479                 do
480                         database_build_patch_reconf "$origin"
481                 done
482                 program_deregister_stage_complete INSPECT_ALL_DEPENDENCIES
483         fi
484         message_echo
485 }
486 program_exec_and_record_completion PATCH_TO_TMPDB_REFLECT_CONF_CHANGES
487
488 # ============= Database construction =============
489
490 # Execute command operations which must be done before building the temporary database
491 command_exec_before_building_tempdb "$@"
492
493 # Meta process for redo
494 PROGRAM_DEPENDS=''
495 _program_exec_and_record_completion__operation ()
496 {
497         rm -f "${DBDIR}/new_success_in_current_run"
498         [ "x$COMMAND_MODE" = xredo ] || return 0
499         message_echo "[REDO mode]"
500         message_echo
501 }
502 program_exec_and_record_completion REDO_INIT
503
504 # Determine specified targets
505 PROGRAM_DEPENDS=''
506 _program_exec_and_record_completion__operation ()
507 {
508         local tag level dbsuffix
509         message_section_title "Determining specified targets"
510         cat "${DBDIR}/stage.loop_list/target_itself.specified" \
511                 "${DBDIR}/stage.loop_list/target_dependents.specified" \
512                 "${DBDIR}/stage.loop_list/target_requirements.specified" \
513                 "${DBDIR}/need.list" \
514                 "${DBDIR}/targets_specified_so_far" 2> /dev/null \
515                 | sort -u > ${DBDIR}/targets_specified_so_far.tmp
516         mv "${DBDIR}/targets_specified_so_far.tmp" "${DBDIR}/targets_specified_so_far"
517         rm -f "${DBDIR}/stage.loop_list/target_itself.specified" \
518                 "${DBDIR}/stage.loop_list/target_dependents.specified" \
519                 "${DBDIR}/stage.loop_list/target_requirements.specified"
520         if [ -n "$opt_target_itself$opt_target_dependents$opt_target_requirements" ]
521         then
522                 options_select_new_ports_if_duplicated O \
523                         "${DBDIR}/stage.loop_list/target_itself.specified" "$opt_target_itself"
524                 options_select_new_ports_if_duplicated t \
525                         "${DBDIR}/stage.loop_list/target_dependents.specified" "$opt_target_dependents"
526                 options_select_new_ports_if_duplicated T \
527                         "${DBDIR}/stage.loop_list/target_requirements.specified" "$opt_target_requirements"
528                 if [ `cat "${DBDIR}/stage.loop_list/target_itself.specified" \
529                         "${DBDIR}/stage.loop_list/target_dependents.specified" \
530                         "${DBDIR}/stage.loop_list/target_requirements.specified" | wc -l` -eq 0 ]
531                 then
532                         message_echo "ERROR: No matching port for target globs." >&2
533                         message_echo >&2
534                         exit 1
535                 fi
536                 cat "${DBDIR}/stage.loop_list/target_itself.specified" \
537                         "${DBDIR}/stage.loop_list/target_dependents.specified" \
538                         "${DBDIR}/stage.loop_list/target_requirements.specified" \
539                         | sort -u > ${TMPDIR}/DETERMINE_SPECIFIED_TARGETS.reset
540                 cat "${TMPDIR}/DETERMINE_SPECIFIED_TARGETS.reset" "${DBDIR}/need.list" 2> /dev/null \
541                         | sort -u > ${DBDIR}/need.list.tmp
542                 mv "${DBDIR}/need.list.tmp" "${DBDIR}/need.list"
543                 sort -u "${DBDIR}/need.list" "${DBDIR}/targets_specified_so_far" \
544                         > ${DBDIR}/targets_specified_so_far.tmp
545                 mv "${DBDIR}/targets_specified_so_far.tmp" "${DBDIR}/targets_specified_so_far"
546                 for tag in all run build none
547                 do
548                         for level in direct full
549                         do
550                                 dbsuffix=$tag.$level
551                                 {
552                                         cat "${TMPDIR}/DETERMINE_SPECIFIED_TARGETS.reset"
553                                         cat "${DBDIR}/stage.loop_list/target_dependents.specified" | while read origin
554                                         do
555                                                 nodedir=${DBDIR}/requires/$origin
556                                                 cat "$nodedir/dependents.$dbsuffix" 2> /dev/null
557                                         done
558                                         cat "${DBDIR}/stage.loop_list/target_requirements.specified" | while read origin
559                                         do
560                                                 nodedir=${DBDIR}/requires/$origin
561                                                 cat "$nodedir/requirements.$dbsuffix" 2> /dev/null
562                                         done
563                                 } | sort -u | while read origin
564                                 do
565                                         fileedit_rm_a_line "$origin" "${DBDIR}/success.$dbsuffix.list"
566                                         fileedit_rm_a_line "$origin" "${DBDIR}/todo_after_requirements_succeed.$dbsuffix.list"
567                                         rm -f "${DBDIR}/requires/$origin/succeeded_once"
568                                 done
569                         done
570                 done
571         fi
572         message_echo
573 }
574 program_exec_and_record_completion DETERMINE_SPECIFIED_TARGETS
575
576 # Show specified targets
577 if [ -n "$opt_target_itself$opt_target_dependents$opt_target_requirements" -a $opt_batch_mode = no ]
578 then
579         message_echo "INFO: (Re/de-)installation will be carried out only for the targets:"
580         echo
581         if [ `wc -l < ${DBDIR}/stage.loop_list/target_itself.specified` -gt 0 ]
582         then
583                 message_echo "[Targets only]"
584                 echo "----------------------------------------"
585                 cat "${DBDIR}/stage.loop_list/target_itself.specified"
586                 echo "----------------------------------------"
587                 echo
588         fi
589         if [ `wc -l < ${DBDIR}/stage.loop_list/target_dependents.specified` -gt 0 ]
590         then
591                 message_echo "[Targets with their `options_get_dependency_msgterm` dependents]"
592                 echo "----------------------------------------"
593                 cat "${DBDIR}/stage.loop_list/target_dependents.specified"
594                 echo "----------------------------------------"
595                 echo
596         fi
597         if [ `wc -l < ${DBDIR}/stage.loop_list/target_requirements.specified` -gt 0 ]
598         then
599                 message_echo "[Targets with their `options_get_dependency_msgterm` requirements]"
600                 echo "----------------------------------------"
601                 cat "${DBDIR}/stage.loop_list/target_requirements.specified"
602                 echo "----------------------------------------"
603                 echo
604         fi
605 fi
606
607 # Determine all target ports
608 PROGRAM_DEPENDS='DETERMINE_SPECIFIED_TARGETS COLLECT_ALL_INSTALLED_PACKAGES'
609 _program_exec_and_record_completion__operation ()
610 {
611         message_section_title "Determining all target ports"
612         {
613                 if [ $opt_only_target_scope = no ]
614                 then
615                         cat "${DBDIR}/installed_ports" 2> /dev/null || :
616                 fi
617                 cat "${DBDIR}/stage.loop_list/target_itself.specified" || :
618                 cat "${DBDIR}/stage.loop_list/target_dependents.specified" || :
619                 cat "${DBDIR}/stage.loop_list/target_requirements.specified" || :
620                 cat "${DBDIR}/targets_specified_so_far" || :
621         }  2> /dev/null | sort -u > "${DBDIR}/stage.loop_list/ports_to_inspect"
622         message_echo
623 }
624 program_exec_and_record_completion DETERMINE_ALL_TARGET_PORTS
625
626 # Inspection of all dependencies
627 PROGRAM_DEPENDS='PARSE_CONF DETERMINE_ALL_TARGET_PORTS'
628 _program_exec_restartable_loop_operation__routine ()
629 {
630         local origin
631         origin=$1
632         database_build_inspect_dependencies "$origin"
633 }
634 _program_exec_and_record_completion__operation ()
635 {
636         local DEPTH_INDEX 
637         message_section_title "Inspecting dependencies of the all installed packages"
638         [ $opt_only_target_scope = no -a -n "$opt_target_itself$opt_target_dependents$opt_target_requirements" ] && \
639                 message_echo "INFO: Ports which seem irrelevant to the targets are also inspected in order to get complete information."
640         DEPTH_INDEX='--'
641         program_exec_restartable_loop_operation ports_to_inspect
642         database_build_post_inspect_dependencies
643         message_echo
644 }
645 program_exec_and_record_completion INSPECT_ALL_DEPENDENCIES
646
647 # Convert dependency-lists to actual ones
648 PROGRAM_DEPENDS='INSPECT_ALL_DEPENDENCIES'
649 _program_exec_restartable_loop_operation__routine ()
650 {
651         local origin table dbtag level tag target
652         origin=$1
653         for table in dependents requirements
654         do
655                 for dbtag in requires obsolete
656                 do
657                         for level in direct full
658                         do
659                                 for tag in all run build
660                                 do
661                                         target=${DBDIR}/$dbtag/$origin/${table}.${tag}.${level}
662                                         if [ -e "$target.src" ]
663                                         then
664                                                 sed -E -f "${DBDIR}/REPLACE.complete_sed_pattern" "$target.src" \
665                                                         | grep -v '^$' | sort -u > $target.tmp
666                                                 [ -e "$target" ] && ! diff "$target.tmp" "$target" > /dev/null \
667                                                         && echo "$origin" >> ${DBDIR}/update_dependencies
668                                                 mv "$target.tmp" "$target"
669                                         else
670                                                 [ -e "$target" ] && echo "$origin" >> ${DBDIR}/update_dependencies
671                                                 rm -f "$target"
672                                         fi
673                                 done
674                         done
675                 done
676         done
677 }
678 _program_exec_and_record_completion__operation ()
679 {
680         message_section_title "Conversion of dependency-lists to actual ones"
681         program_exec_restartable_loop_operation convert_dependency_lists
682         sort -u "${DBDIR}/update_dependencies" > ${DBDIR}/update_dependencies.tmp
683         mv "${DBDIR}/update_dependencies.tmp" "${DBDIR}/update_dependencies"
684         str_escape_regexp_filter < ${DBDIR}/update_dependencies \
685                 | sed 's/^/^/; s/$/$/' > ${DBDIR}/update_dependencies.grep_pattern
686         for tag in all run build
687         do
688                 ( cd "${DBDIR}/requires" && \
689                         find . -depth 3 -type f -name requirements.${tag}.full | sed 's|^./||;s|/[^/]*$||' ) \
690                         | grep -v -E -f "${DBDIR}/update_dependencies.grep_pattern" \
691                         | str_escape_regexp_filter | sed 's/^/^/; s/$/$/' \
692                         > ${TMPDIR}/convert_requirements_list:full_complete.grep_pattern || :
693                 ( cd "${DBDIR}/requires" && \
694                         find . -depth 3 -type f -name requirements.${tag}.direct | sed 's|^./||;s|/[^/]*$||' ) \
695                         | grep -v -E -f "${TMPDIR}/convert_requirements_list:full_complete.grep_pattern" \
696                         > ${DBDIR}/stage.loop_list/complete_${tag}time_reqlists || :
697         done
698         for inspected_level_tmp in direct node
699         do
700                 cat "${DBDIR}/ports.inspected.${inspected_level_tmp}.list" || :
701         done 2> /dev/null | sort -u > ${DBDIR}/stage.loop_list/trim_dependency_lists_rm_uninspected_ports
702         find "${DBDIR}/requires" -depth 2 -type d > ${DBDIR}/stage.loop_list/inspect_dependent
703         [ -e "${DBDIR}/dependents_files" ] && \
704                 mv "${DBDIR}/dependents_files" "${DBDIR}/dependents_files.prev"
705         rm -f "${DBDIR}/stage.loop_list/make_dependents_lists_unique.tmp" "${DBDIR}/dependents_files.tmp"
706         message_echo
707 }
708 program_exec_and_record_completion CONVERT_REQUIREMENTS_LIST
709
710 # Completion of recursive requirement lists
711 for _REQUIREMENT_LISTS_tag in all run build
712 do
713         PROGRAM_DEPENDS='CONVERT_REQUIREMENTS_LIST'
714         _program_exec_restartable_loop_operation__routine ()
715         {
716                 local tag dbpath origin
717                 tag=${_REQUIREMENT_LISTS_tag}
718                 dbpath=$1
719                 origin=`str_dirpath_to_origin "$dbpath"`
720                 database_build_get_complete_recursive_dependency requirements.${tag} "$origin" > /dev/null
721         }
722         _program_exec_and_record_completion__operation ()
723         {
724                 local tag
725                 tag=${_REQUIREMENT_LISTS_tag}
726                 message_section_title "Completion of ${tag}-time requirement lists"
727                 program_exec_restartable_loop_operation complete_${tag}time_reqlists
728                 message_echo
729         }
730         program_exec_and_record_completion REQUIREMENT_LISTS:${_REQUIREMENT_LISTS_tag}
731 done
732
733 # Trim dependency lists by removing uninspected ports
734 if [ $opt_only_target_scope = yes ]
735 then
736         PROGRAM_DEPENDS='INSPECT_ALL_DEPENDENCIES CONVERT_REQUIREMENTS_LIST'
737         _program_exec_restartable_loop_operation__routine ()
738         {
739                 local dbpath tag level srcdb
740                 dbpath=$1
741                 for tag in all run build
742                 do
743                         for level in direct full
744                         do
745                                 srcdb=requirements.${tag}.${level}
746                                 [ -e "$dbpath/$srcdb" ] || continue
747                                 grep -E -f "${DBDIR}/inspected_ports.grep_pattern" "$dbpath/$srcdb" \
748                                         > $dbpath/$srcdb.tmp || :
749                                 mv "$dbpath/$srcdb.tmp" "$dbpath/$srcdb"
750                         done
751                 done
752         }
753         _program_exec_and_record_completion__operation ()
754         {
755                 message_section_title "Trimming dependency lists by removing uninspected ports"
756                 program_exec_restartable_loop_operation trim_dependency_lists_rm_uninspected_ports
757                 message_echo
758         }
759         program_exec_and_record_completion TRIM_DEPENDENCY_LISTS_RM_UNINSPECTED_PORTS
760 fi
761
762 # Inspection of dependents
763 PROGRAM_DEPENDS='INSPECT_ALL_DEPENDENCIES CONVERT_REQUIREMENTS_LIST TRIM_DEPENDENCY_LISTS_RM_UNINSPECTED_PORTS'
764 _program_exec_restartable_loop_operation__routine ()
765 {
766         local dbpath origin tag level srcdb dstdb
767         dbpath=$1
768         origin=`str_dirpath_to_origin "$dbpath"`
769         for tag in all run build
770         do
771                 for level in direct full
772                 do
773                         srcdb=requirements.${tag}.${level}
774                         dstdb=dependents.${tag}.${level}
775                         [ -e "$dbpath/$srcdb" ] || continue
776                         while read origin_requirement
777                         do
778                                 dstpath=${DBDIR}/requires/$origin_requirement
779                                 echo "$dstpath/$dstdb" >> ${DBDIR}/dependents_files.tmp
780                                 [ "$dstpath/$dstdb" -nt "$dbpath/$srcdb" ] && continue
781                                 [ -d "$dstpath" ] || mkdir -p "$dstpath"
782                                 echo "$origin" >> $dstpath/$dstdb.raw
783                                 echo "$dstpath/$dstdb" >> ${DBDIR}/stage.loop_list/make_dependents_lists_unique.tmp
784                         done < $dbpath/$srcdb
785                 done
786         done
787 }
788 _program_exec_and_record_completion__operation ()
789 {
790         local dbrequires_valesc
791         message_section_title "Inspection of dependents"
792         dbrequires_valesc=`str_escape_replaceval "${DBDIR}/requires/"`
793         program_exec_restartable_loop_operation inspect_dependent
794         sort -u "${DBDIR}/stage.loop_list/make_dependents_lists_unique.tmp" 2> /dev/null \
795                 > ${DBDIR}/stage.loop_list/make_dependents_lists_unique || :
796         sort -u "${DBDIR}/dependents_files.tmp" 2> /dev/null > ${DBDIR}/dependents_files || :
797         [ -e "${DBDIR}/make_dependents_lists_unique.prev" ] && \
798                 fileedit_manipulate_old_lines "${DBDIR}/dependents_files.prev" "${DBDIR}/dependents_files" \
799                 | xargs rm -f
800         message_echo
801 }
802 program_exec_and_record_completion INSPECT_DEPENDENTS
803
804 # Remove duplicated lines in dependents lists
805 PROGRAM_DEPENDS='CONVERT_REQUIREMENTS_LIST INSPECT_DEPENDENTS'
806 _program_exec_restartable_loop_operation__routine ()
807 {
808         local dbpath tag level dstdb
809         dstdb=$1
810         cat "$dstdb" "$dstdb.raw" 2> /dev/null | sort -u > $dstdb.tmp
811         mv "$dstdb.tmp" "$dstdb"
812         rm -f "$dstdb.raw"
813 }
814 _program_exec_and_record_completion__operation ()
815 {
816         local dbrequires_valesc
817         message_section_title "Removing duplicated items in dependents lists"
818         program_exec_restartable_loop_operation make_dependents_lists_unique
819         message_echo
820 }
821 program_exec_and_record_completion MAKE_DEPENDENTS_LISTS_UNIQUE
822
823 # Preparation of target attribute information
824 for _TARGET_ATTR_INFO_table in requirements dependents itself
825 do
826         [ `cat "${DBDIR}/stage.loop_list/target_${_TARGET_ATTR_INFO_table}.replaced.specified" 2> /dev/null \
827                 | wc -l` -gt 0 ] || continue
828         PROGRAM_DEPENDS='DETERMINE_SPECIFIED_TARGETS CONVERT_REQUIREMENTS_LIST'
829         _program_exec_restartable_loop_operation__routine ()
830         {
831                 local origin dbtargets_valesc table
832                 origin=$1
833                 dbtargets_valesc=`str_escape_replaceval "${DBDIR}/targets/"`
834                 table=${_TARGET_ATTR_INFO_table}
835                 for database in requires initial
836                 do
837                         dbpath=${DBDIR}/$database/$origin
838                         dstpath=${DBDIR}/targets/$origin
839                         [ -d "$dstpath" ] || mkdir -p "$dstpath"
840                         touch "$dstpath/target_itself"
841                         echo "$origin" >> ${DBDIR}/all_targets.lst
842                         [ $table = itself ] && continue
843                         for tag in all run build
844                         do
845                                 for level in direct full
846                                 do
847                                         srcdb=${table}.${tag}.${level}
848                                         dstdb=target_${database}_${table}.${tag}.${level}
849                                         [ -e "$dbpath/$srcdb" ] || continue
850                                         cat "$dbpath/$srcdb" >> ${DBDIR}/all_targets.lst
851                                         sed -E "s/^/$dbtargets_valesc/; s|$|/$dstdb|" "$dbpath/$srcdb" \
852                                                 | fileedit_add_a_line_to_files_if_new "$origin"
853                                 done
854                         done
855                 done
856         }
857         _program_exec_and_record_completion__operation ()
858         {
859                 local table
860                 table=${_TARGET_ATTR_INFO_table}
861                 message_section_title "Preparation of target attribute information for dependency [$table]"
862                 program_exec_restartable_loop_operation target_$table.replaced.specified
863                 message_echo
864         }
865         program_exec_and_record_completion TARGET_ATTR_INFO:${_TARGET_ATTR_INFO_table}
866 done
867
868 # Post-process after the preparation of target attribute information
869 PROGRAM_DEPENDS='MAKE_DEPENDENTS_LISTS_UNIQUE TARGET_ATTR_INFO:requirements TARGET_ATTR_INFO:dependents'
870 _program_exec_and_record_completion__operation ()
871 {
872         message_section_title "Post-process after the preparation of target attribute information"
873         sort -u "${DBDIR}/all_targets.lst" 2> /dev/null \
874                 | grep -E -f "${DBDIR}/inspected_ports.grep_pattern" \
875                 | sed -E -f "${DBDIR}/REPLACE.complete_sed_pattern" \
876                 > ${DBDIR}/all_targets.lst.tmp || :
877         mv "${DBDIR}/all_targets.lst.tmp" "${DBDIR}/all_targets.lst"
878         find "${DBDIR}/targets" -depth 2 -type d > ${DBDIR}/stage.loop_list/build_complement_to_new_dependents_for_targets 2> /dev/null || :
879         {
880                 cat "${DBDIR}/all_targets.lst" "${DBDIR}/need.with_replaced.list" 2> /dev/null || :
881                 find "${DBDIR}/requires" -depth 3 -type f -name installed_version \
882                         | sed -E 's|.*/([^/]+/[^/]+)/[^/]*$|\1|'
883         } | sort -u > ${DBDIR}/stage.loop_list/inspect_necessity
884         cp /dev/null "${DBDIR}/stage.loop_list/parse_target_attr_info"
885         find -E "${DBDIR}/requires" -depth 3 -type f -regex '.*/necessary_port\.(direct|full)$' -delete
886         message_echo
887 }
888 program_exec_and_record_completion TARGET_ATTR_INFO_POSTPROCESS
889
890 # Build of data on complement to new dependents for target attribute information
891 PROGRAM_DEPENDS='TARGET_ATTR_INFO_POSTPROCESS TARGET_ATTR_INFO:requirements TARGET_ATTR_INFO:dependents CONVERT_REQUIREMENTS_LIST'
892 _program_exec_restartable_loop_operation__routine ()
893 {
894         local dbpath origin
895         dbpath=$1
896         origin=`str_dirpath_to_origin "$dbpath"`
897         database_build_complement_to_new_dependents_for_targets "$origin"
898 }
899 _program_exec_and_record_completion__operation ()
900 {
901         message_section_title "Build of data on complement to new dependents for target attribute information"
902         program_exec_restartable_loop_operation build_complement_to_new_dependents_for_targets
903         sort -u "${DBDIR}/stage.loop_list/parse_target_attr_info" > ${DBDIR}/stage.loop_list/parse_target_attr_info.tmp
904         mv "${DBDIR}/stage.loop_list/parse_target_attr_info.tmp" "${DBDIR}/stage.loop_list/parse_target_attr_info"
905         message_echo
906 }
907 program_exec_and_record_completion COMPLEMENT_TO_NEW_DEPENDENTS_FOR_TARGET_ATTR_INFO
908
909 # Parse target attribute information
910 PROGRAM_DEPENDS='COMPLEMENT_TO_NEW_DEPENDENTS_FOR_TARGET_ATTR_INFO'
911 _program_exec_restartable_loop_operation__routine ()
912 {
913         local dbpath origin
914         dbpath=$1
915         origin=`str_dirpath_to_origin "$dbpath"`
916         database_build_target_attributes "$origin"
917 }
918 _program_exec_and_record_completion__operation ()
919 {
920         message_section_title "Parsing target attribute information"
921         program_exec_restartable_loop_operation parse_target_attr_info
922         message_echo
923 }
924 program_exec_and_record_completion PARSE_TARGET_ATTR_INFO
925
926 # Inspection of necessity
927 PROGRAM_DEPENDS='TARGET_ATTR_INFO_POSTPROCESS REQUIREMENT_LISTS:run-time REQUIREMENT_LISTS:build-time INSPECT_ALL_DEPENDENCIES'
928 _program_exec_restartable_loop_operation__routine ()
929 {
930         local origin
931         origin=$1
932         for level in direct full
933         do
934                 database_build_inspect_necessity_for_only_new_upgrade "$origin" "$level"
935         done
936 }
937 _program_exec_and_record_completion__operation ()
938 {
939         message_section_title "Inspection of necessity"
940         program_exec_restartable_loop_operation inspect_necessity
941         for level in direct full
942         do
943                 find "${DBDIR}/requires" -depth 3 -type f -name "necessary_port.${level}" \
944                         > ${DBDIR}/stage.loop_list/necessary_ports.${level}
945         done
946         message_echo
947 }
948 program_exec_and_record_completion INSPECT_NECESSITY
949
950 # Inspection of necessary upgrades
951 for _NECESSARY_UPDATES_level in direct full
952 do
953         PROGRAM_DEPENDS='INSPECT_NECESSITY INSPECT_ALL_DEPENDENCIES MAKE_DEPENDENTS_LISTS_UNIQUE'
954         _program_exec_restartable_loop_operation__routine ()
955         {
956                 local markerpath level dbpath origin tag
957                 markerpath=$1
958                 level=${_NECESSARY_UPDATES_level}
959                 dbpath=`dirname "$markerpath"`
960                 origin=`str_dirpath_to_origin "$dbpath"`
961                 database_query_does_a_port_need_update "$origin" || return 0
962                 for tag in all run build none
963                 do
964                         touch "$dbpath/necessary_upgrade.$tag.${level}"
965                         [ -e "$dbpath/dependents.$tag.${level}" ] || continue
966                         while read origin_dependent
967                         do
968                                 touch "${DBDIR}/requires/$origin_dependent/necessary_upgrade.$tag.${level}"
969                         done < $dbpath/dependents.$tag.${level}
970                 done
971         }
972         _program_exec_and_record_completion__operation ()
973         {
974                 local level
975                 level=${_NECESSARY_UPDATES_level}
976                 message_section_title "Inspection of necessary upgrades at the $level level"
977                 program_exec_restartable_loop_operation necessary_ports.${level}
978                 message_echo
979         }
980         program_exec_and_record_completion NECESSARY_UPDATES:${_NECESSARY_UPDATES_level}
981 done
982
983 # Preparation for inspection of new leaf ports
984 if [ ! -e "${DBDIR}/inspected_ports_only_partially" ]
985 then
986         PROGRAM_DEPENDS='INSPECT_ALL_DEPENDENCIES MAKE_DEPENDENTS_LISTS_UNIQUE PARSE_CONF'
987         _program_exec_and_record_completion__operation ()
988         {
989                 message_section_title "Preparation for inspection of new leaf ports"
990                 find "${DBDIR}/requires" -depth 3 -type f -name dependents.all.full \
991                         | sed -E 's|.*/([^/]+/[^/]+)/[^/]+$|\1|' \
992                         | sort -u > ${TMPDIR}/PREPARE_INSPECT_LEAF_PORTS:nonleaf_ports
993                 sort -u "${DBDIR}/inspected_ports" > ${TMPDIR}/PREPARE_INSPECT_LEAF_PORTS:inspected_ports
994                 fileedit_manipulate_new_lines \
995                         "${TMPDIR}/PREPARE_INSPECT_LEAF_PORTS:nonleaf_ports" \
996                         "${TMPDIR}/PREPARE_INSPECT_LEAF_PORTS:inspected_ports" \
997                         | grep -v -E -f "${DBDIR}/conf/HOLD_PORTS.grep_pattern" \
998                         > ${DBDIR}/stage.loop_list/leaf_ports_primary_candidates || :
999                 cp /dev/null "${DBDIR}/grep.leaf_ports.pattern"
1000                 cp /dev/null "${DBDIR}/stage.loop_list/leaf_ports_secondary_candidates"
1001                 message_echo
1002         }
1003         program_exec_and_record_completion PREPARE_INSPECT_LEAF_PORTS
1004 fi
1005
1006 # Inspection of new primary leaf ports
1007 if [ ! -e "${DBDIR}/inspected_ports_only_partially" ]
1008 then
1009         PROGRAM_DEPENDS='INSPECT_ALL_DEPENDENCIES MAKE_DEPENDENTS_LISTS_UNIQUE PREPARE_INSPECT_LEAF_PORTS PARSE_CONF'
1010         _program_exec_restartable_loop_operation__routine ()
1011         {
1012                 local origin origin_ini origin_esc dbpath origin_req
1013                 origin=$1
1014                 pkgsys_is_pkgtool "$origin" && return
1015                 dbpath=${DBDIR}/requires/$origin
1016                 origin_esc=`str_escape_regexp "$origin"`
1017                 grep -q -E "^$origin_esc$" "${DBDIR}/need.with_replaced.list" 2> /dev/null && return
1018                 if ! grep -q -E "^$origin_esc$" "${DBDIR}/noneed.list" 2> /dev/null
1019                 then
1020                         if [ -e "$dbpath/initial_orig" ]
1021                         then
1022                                 origin_ini=`cat "$dbpath/initial_orig"`
1023                                 [ -e "${DBDIR}/initial/$origin_ini/installed_version" \
1024                                         -a `cat "${DBDIR}/initial/$origin_ini/dependents.all.full" 2> /dev/null | wc -l` -eq 0 ] \
1025                                         && return
1026                         fi
1027                         [ -e "${DBDIR}/initial/$origin/installed_version" \
1028                                 -a `cat "${DBDIR}/initial/$origin/dependents.all.full" 2> /dev/null | wc -l` -eq 0 ] \
1029                                 && return
1030                 fi
1031                 if [ -e "$dbpath/requirements.all.full" ]
1032                 then
1033                         grep -v -E -f "${DBDIR}/conf/HOLD_PORTS.grep_pattern" "$dbpath/requirements.all.full" | \
1034                                 fileedit_add_lines_if_new "${DBDIR}/stage.loop_list/leaf_ports_secondary_candidates" || :
1035                 fi
1036                 fileedit_add_a_line_if_new "^$origin_esc$" "${DBDIR}/grep.leaf_ports.pattern"
1037         }
1038         _program_exec_and_record_completion__operation ()
1039         {
1040                 local num_leaves num_leaves_prev
1041                 message_section_title "Inspection of new primary leaf ports"
1042                 program_exec_restartable_loop_operation leaf_ports_primary_candidates
1043                 wc -l < ${DBDIR}/grep.leaf_ports.pattern | tr -d ' ' > ${DBDIR}/num_leaves
1044                 cp /dev/null "${DBDIR}/leaf_ports_secondary_candidates.new_requirements"
1045                 message_echo "  `cat "${DBDIR}/num_leaves"` primary leaf port(s) is/are found."
1046                 message_echo
1047         }
1048         program_exec_and_record_completion INSPECT_PRIMARY_LEAF_PORTS
1049 fi
1050
1051 # Inspection of requirements of new leaf ports
1052 if [ ! -e "${DBDIR}/inspected_ports_only_partially" ]
1053 then
1054         PROGRAM_DEPENDS='INSPECT_ALL_DEPENDENCIES MAKE_DEPENDENTS_LISTS_UNIQUE INSPECT_PRIMARY_LEAF_PORTS PARSE_CONF'
1055         _program_exec_and_record_completion__operation ()
1056         {
1057                 local num_leaves num_leaves_prev num_inspect num_leaves_new
1058                 message_section_title "Inspection of requirements of new leaf ports"
1059                 message_echo "INFO: The inspection proceeds by iterative method."
1060                 while :
1061                 do
1062                         _program_exec_restartable_loop_operation__routine ()
1063                         {
1064                                 local origin origin_esc dbpath
1065                                 origin=$1
1066                                 pkgsys_is_pkgtool "$origin" && return
1067                                 dbpath=${DBDIR}/requires/$origin
1068                                 origin_esc=`str_escape_regexp "$origin"`
1069                                 grep -q -E "^$origin_esc$" "${DBDIR}/need.with_replaced.list" 2> /dev/null && return
1070                                 grep -E -v -f "${DBDIR}/grep.leaf_ports.pattern" \
1071                                         "$dbpath/dependents.all.full" > /dev/null 2>&1 && return
1072                                 cat "$dbpath/requirements.all.full" 2> /dev/null \
1073                                         >> ${DBDIR}/leaf_ports_secondary_candidates.new_requirements || :
1074                                 fileedit_add_a_line_if_new "^$origin_esc$" "${DBDIR}/grep.leaf_ports.pattern"
1075                         }
1076                         program_exec_restartable_loop_operation leaf_ports_secondary_candidates
1077                         num_leaves_prev=`cat "${DBDIR}/num_leaves"`
1078                         num_leaves=`wc -l < ${DBDIR}/grep.leaf_ports.pattern | tr -d ' '`
1079                         num_leaves_new=`echo $(($num_leaves-$num_leaves_prev)) | tr -d ' '`
1080                         if [ $num_leaves_new -eq 0 ]
1081                         then
1082                                 message_echo "  No more leaf port is found."
1083                                 message_echo "  $num_leaves leaf port(s) is/are found in total."
1084                                 break
1085                         fi
1086                         {
1087                                 grep -E -v -f "${DBDIR}/grep.leaf_ports.pattern" \
1088                                         "${DBDIR}/stage.loop_list/leaf_ports_secondary_candidates" || :
1089                                 cat "${DBDIR}/leaf_ports_secondary_candidates.new_requirements" || :
1090                         } | grep -v -E -f "${DBDIR}/conf/HOLD_PORTS.grep_pattern" | sort -u \
1091                                 > ${DBDIR}/stage.loop_list/leaf_ports_secondary_candidates.tmp || :
1092                         program_reset_loop_for_stage INSPECT_REQUIREMENTS_OF_LEAF_PORTS
1093                         mv "${DBDIR}/stage.loop_list/leaf_ports_secondary_candidates.tmp" \
1094                                 "${DBDIR}/stage.loop_list/leaf_ports_secondary_candidates"
1095                         cp /dev/null "${DBDIR}/leaf_ports_secondary_candidates.new_requirements"
1096                         echo "$num_leaves" > ${DBDIR}/num_leaves
1097                         num_inspect=`wc -l < ${DBDIR}/stage.loop_list/leaf_ports_secondary_candidates | tr -d ' '`
1098                         message_echo "  $num_leaves_new leaf port(s) is/are newly found; continue for $num_inspect candidate(s)."
1099                 done
1100                 grep -E -f "${DBDIR}/grep.leaf_ports.pattern" "${DBDIR}/inspected_ports" | sort -u > ${DBDIR}/leaf_ports || :
1101                 message_echo
1102         }
1103         program_exec_and_record_completion INSPECT_REQUIREMENTS_OF_LEAF_PORTS
1104 fi
1105
1106 # Order the ports considering dependencies
1107 PROGRAM_DEPENDS='CONVERT_REQUIREMENTS_LIST'
1108 _program_exec_and_record_completion__operation ()
1109 {
1110         message_section_title "Ordering dependencies"
1111         if ! database_build_order_ports_considering_dependencies
1112         then
1113                 message_echo "ERROR: Unsatisfied dependencies are remained:" >&2
1114                 message_cat "${DBDIR}/unsatisfied.list"
1115                 message_echo "*** Aborted by ${APPNAME}"
1116                 message_echo "The ports tree seems broken. You might have caught an incomplete version."
1117                 message_echo "You are encouraged to update the ports tree by portsnap(8)."
1118                 message_echo "Then execute"
1119                 message_echo " ${APPNAME} clean"
1120                 message_echo "before restart."
1121                 temp_terminate_process () { :; }
1122                 exit 1
1123         fi
1124         message_echo
1125 }
1126 program_exec_and_record_completion ORDER_ALL_DEPENDENCIES
1127
1128 # Selection of removing leaf ports
1129 PROGRAM_DEPENDS='INSPECT_REQUIREMENTS_OF_LEAF_PORTS'
1130 _program_exec_and_record_completion__operation ()
1131 {
1132         message_section_title "Selection of removing leaf ports"
1133         deinstall_select_leaf_ports_to_delete
1134         message_echo
1135 }
1136 program_exec_and_record_completion SELECT_LEAF_PORTS
1137
1138 # Selection of removing obsolete ports
1139 PROGRAM_DEPENDS='INSPECT_ALL_DEPENDENCIES PARSE_CONF'
1140 _program_exec_and_record_completion__operation ()
1141 {
1142         message_section_title "Selection of removing obsolete ports"
1143         deinstall_select_obsolete_ports_to_delete
1144         message_echo
1145 }
1146 program_exec_and_record_completion SELECT_OBSOLETE_PORTS
1147
1148 # Collection of leaf ports to delete
1149 if [ ! -e "${DBDIR}/inspected_ports_only_partially" ]
1150 then
1151         PROGRAM_DEPENDS='SELECT_LEAF_PORTS'
1152         _program_exec_and_record_completion__operation ()
1153         {
1154                 local src src_unselected reqptn_file src_with_initial_origins
1155                 message_section_title "Collecting leaf ports to delete"
1156                 src=${DBDIR}/leaf_ports
1157                 src_unselected=${DBDIR}/leaf_ports_to_delete.unselected
1158                 src_with_initial_origins=${DBDIR}/leaf_ports.with_ini
1159                 reqptn_file=${DBDIR}/leaf_ports.requirements_of_unselected.grep_pattern
1160                 cat "$src_unselected" 2> /dev/null | while read origin
1161                 do
1162                         cat "${DBDIR}/requires/$origin/requirements.all.full" || :
1163                 done | sort -u | str_escape_regexp_filter \
1164                         | sed 's/^/^/;s/$/$/' > $reqptn_file
1165                 database_query_add_initial_origins < $src > $src_with_initial_origins
1166                 message_echo
1167         }
1168         program_exec_and_record_completion COLLECT_LEAF_PORTS_TO_DELETE
1169 fi
1170
1171 # Collection of obsolete ports to delete
1172 PROGRAM_DEPENDS='SELECT_OBSOLETE_PORTS'
1173 _program_exec_and_record_completion__operation ()
1174 {
1175         local src src_selected src_unselected dst_selected reqptn_file
1176         message_section_title "Collecting obsolete ports to delete"
1177         src=${DBDIR}/obsolete_ports.can_be_deleted
1178         src_selected=${DBDIR}/obsolete_ports_to_delete.selected
1179         src_unselected=${DBDIR}/obsolete_ports_to_delete.unselected
1180         dst_selected=${DBDIR}/obsolete_ports_to_delete
1181         reqptn_file=${DBDIR}/obsolete_ports.requirements_of_unselected.grep_pattern
1182         cat "$src_unselected" 2> /dev/null | while read origin
1183         do
1184                 cat "${DBDIR}/initial/$origin/requirements.run.full" || :
1185                 cat "${DBDIR}/obsolete/$origin/requirements.run.full" || :
1186         done | sort -u | str_escape_regexp_filter \
1187                 | sed 's/^/^/;s/$/$/' > $reqptn_file
1188         grep -v -E -f "$reqptn_file" "$src_selected" > $dst_selected 2> /dev/null || :
1189         message_echo
1190 }
1191 program_exec_and_record_completion COLLECT_OBSOLETE_PORTS_TO_DELETE
1192
1193 # Set up the list of ports to reinstall
1194 PROGRAM_DEPENDS='ORDER_ALL_DEPENDENCIES'
1195 _program_exec_and_record_completion__operation ()
1196 {
1197         message_section_title "Setting up the list of ports to reinstall"
1198         cp -p "${DBDIR}/reinst_order.list" "${DBDIR}/stage.loop_list/reinst_todo"
1199         message_echo
1200 }
1201 program_exec_and_record_completion SETUP_REINST_TODO
1202
1203 # Composition of a list for deinstallation of obsolete and leaf packages
1204 PROGRAM_DEPENDS='COLLECT_LEAF_PORTS_TO_DELETE COLLECT_OBSOLETE_PORTS_TO_DELETE'
1205 _program_exec_and_record_completion__operation ()
1206 {
1207         local reqptn_leaf reqptn_obs leaf_selected leaf_selected_src obs_selected obs_selected_src grepptn preserved
1208         message_section_title "Composing a list for deinstallation of obsolete and leaf packages"
1209         reqptn_leaf=${DBDIR}/leaf_ports.requirements_of_unselected.grep_pattern
1210         reqptn_obs=${DBDIR}/obsolete_ports.requirements_of_unselected.grep_pattern
1211         leaf_selected_src=${DBDIR}/leaf_ports_to_delete.selected
1212         leaf_selected=${DBDIR}/leaf_ports_to_delete
1213         obs_selected_src=${DBDIR}/obsolete_ports_to_delete.selected
1214         obs_selected=${DBDIR}/obsolete_ports_to_delete
1215         grepptn=${DBDIR}/ports_to_delete.grep_pattern
1216         grepptn_col1=${DBDIR}/ports_to_delete.grep_pattern_col1
1217         preserved=${TMPDIR}/LIST_DEINST_PKGS::preserved
1218         if [ ! -e "${DBDIR}/inspected_ports_only_partially" ]
1219         then
1220                 cat "$reqptn_leaf" "$reqptn_obs" 2> /dev/null | sort -u > $grepptn
1221                 grep -v -E -f "$grepptn" "$leaf_selected_src" 2> /dev/null \
1222                         | database_query_add_initial_origins > $leaf_selected || :
1223                 cat "$obs_selected" "$leaf_selected" 2> /dev/null || :
1224         else
1225                 rm -f "$leaf_selected"
1226                 cat "$obs_selected" 2> /dev/null
1227         fi | sort -u > ${DBDIR}/stage.loop_list/ports_to_delete
1228         str_escape_regexp_filter < ${DBDIR}/stage.loop_list/ports_to_delete \
1229                 | sed 's/^/^/;s/$/$/' > $grepptn
1230         str_escape_regexp_filter < ${DBDIR}/stage.loop_list/ports_to_delete \
1231                 | sed 's/^/^/;s/$/[[:space:]]/' > $grepptn_col1
1232         cat "${DBDIR}/leaf_ports.with_ini" "${DBDIR}/obsolete_ports" 2> /dev/null \
1233                 | grep -E -v -f "$grepptn" > ${DBDIR}/stage.loop_list/ports_to_restore || :
1234         if [ $opt_batch_mode = no ]
1235         then
1236                 if [ ! -e "${DBDIR}/inspected_ports_only_partially" ] && \
1237                         grep -v -E -f "$grepptn" "$leaf_selected_src" > $preserved 2> /dev/null
1238                 then
1239                         message_echo "INFO: Following leaf ports are preserved because required by other preserved leaf/obsolete ports."
1240                         message_echo "----------------"
1241                         while read origin
1242                         do
1243                                 pkgtag=`cat "${DBDIR}/required/$origin/pkgtag" 2> /dev/null` || :
1244                                 if [ -n "$pkgtag" ]
1245                                 then
1246                                         echo "$origin" "($pkgtag)"
1247                                 else
1248                                         echo "$origin"
1249                                 fi
1250                         done < $preserved
1251                         message_echo "----------------"
1252                 fi
1253                 if grep -v -E -f "$grepptn" "$obs_selected_src" > $preserved 2> /dev/null
1254                 then
1255                         message_echo "INFO: Following obsolete ports are preserved because required by other obsolete ports."
1256                         message_echo "----------------"
1257                         while read origin
1258                         do
1259                                 pkgtag=`cat "${DBDIR}/initial/$origin/installed_version" 2> /dev/null` || :
1260                                 if [ -n "$pkgtag" ]
1261                                 then
1262                                         echo "$origin" "($pkgtag)"
1263                                 else
1264                                         echo "$origin"
1265                                 fi
1266                         done < $preserved
1267                         message_echo "----------------"
1268                 fi
1269         fi
1270         message_echo
1271 }
1272 program_exec_and_record_completion LIST_DEINST_PKGS
1273
1274 # Collect entire distfiles list
1275 if [ $opt_inspect_entire_distinfo = yes ]
1276 then
1277         PROGRAM_DEPENDS=''
1278         _program_exec_and_record_completion__operation ()
1279         {
1280                 message_section_title "Collecting entire distfiles list"
1281                 find "${PORTSDIR}" -depth 3 -name distinfo -exec cat {} \; \
1282                         | grep '^SHA256 ' | sed -E 's/^SHA256 \(([^)]*)\).*/\1/' \
1283                         | sort -u > ${DBDIR}/distfiles.entire.tmp
1284                 mv "${DBDIR}/distfiles.entire.tmp" "${DBDIR}/distfiles.entire"
1285                 message_echo
1286         }
1287         program_exec_and_record_completion COLLECT_ALL_DISTFILES_LIST
1288 fi
1289
1290 # Inspection of all required distfiles
1291 PROGRAM_DEPENDS='INSPECT_ALL_DEPENDENCIES COLLECT_ALL_DISTFILES_LIST'
1292 _program_exec_and_record_completion__operation ()
1293 {
1294         message_section_title "Summarizing distfiles list"
1295         cat "${DBDIR}/distfiles.entire" "${DBDIR}/distfiles.inspected" 2> /dev/null \
1296                 | sort -u | str_escape_regexp_filter \
1297                 | sed 's|^|^\\.\\/|; s|$|$|' > ${DBDIR}/distfiles.grep.pattern || :
1298         message_echo
1299 }
1300 program_exec_and_record_completion DISTFILES_LIST
1301
1302 # Clean up of reinstallation status for preparation
1303 PROGRAM_DEPENDS='REDO_INIT INSPECT_ALL_DEPENDENCIES'
1304 _program_exec_and_record_completion__operation ()
1305 {
1306         message_section_title "Cleaning up of reinstallation status for preparation"
1307         rm -rf "${DBDIR}/status.ports"
1308         message_echo
1309 }
1310 program_exec_and_record_completion CLEANUP_REINST_STATUS
1311
1312 # Completion of building the temporary database
1313 PROGRAM_DEPENDS='REDO_INIT SETUP_REINST_TODO CLEANUP_REINST_STATUS PARSE_CONF INSPECT_ALL_DEPENDENCIES NECESSARY_UPDATES:direct NECESSARY_UPDATES:full PARSE_TARGET_ATTR_INFO MAKE_DEPENDENTS_LISTS_UNIQUE COLLECT_LEAF_PORTS_TO_DELETE'
1314 _program_exec_and_record_completion__operation ()
1315 {
1316         message_section_title "The temporary database is completely built up"
1317         message_echo
1318 }
1319 program_exec_and_record_completion PREPARATION
1320
1321
1322 # ==================================================
1323 # ====================== MAIN ======================
1324 # ==================================================
1325
1326 # Execute command operations which must be done before actual (re/de)installation processes
1327 command_exec_before_actual_re_de_installation "$@"
1328
1329 # Set termination messages
1330 temp_terminate_process ()
1331 {
1332         temp_terminate_process_common
1333 }
1334
1335 # Reinstallation of remained ports
1336 PROGRAM_DEPENDS='PREPARATION'
1337 _program_exec_restartable_loop_operation__routine ()
1338 {
1339         reinstall_exec "$@"
1340 }
1341 _program_exec_and_record_completion__operation ()
1342 {
1343         local _MSG_CURRENT_STAGE_general
1344         _MSG_CURRENT_STAGE_general="reinstallation"
1345         temp_set_msg_current_stage "${_MSG_CURRENT_STAGE_general}"
1346         message_section_title "Reinstallation"
1347         program_exec_restartable_loop_operation reinst_todo
1348         reinstall_restore_conflicts
1349         temp_set_msg_current_stage
1350         message_echo
1351 }
1352 program_exec_and_record_completion REINSTALLATION
1353
1354 # Restoration of obsolete and leaf packages which have been deinstalled but unselected from the deletion list again 
1355 PROGRAM_DEPENDS='REDO_INIT LIST_DEINST_PKGS'
1356 _program_exec_restartable_loop_operation__routine ()
1357 {
1358         deinstall_restore "$@"
1359 }
1360 _program_exec_and_record_completion__operation ()
1361 {
1362         local _MSG_CURRENT_STAGE_general
1363         _MSG_CURRENT_STAGE_general="restoration of unselected obsolete/leaf packages"
1364         temp_set_msg_current_stage "${_MSG_CURRENT_STAGE_general}"
1365         message_section_title "Restoration of unselected obsolete/leaf packages"
1366         program_exec_restartable_loop_operation ports_to_restore
1367         temp_set_msg_current_stage
1368         message_echo
1369 }
1370 program_exec_and_record_completion RESTORE_ONCE_DEINST_PKGS
1371
1372 # Deinstallation of unused obsolete and leaf packages
1373 PROGRAM_DEPENDS='REDO_INIT LIST_DEINST_PKGS'
1374 _program_exec_restartable_loop_operation__routine ()
1375 {
1376         deinstall_exec "$@"
1377 }
1378 _program_exec_and_record_completion__operation ()
1379 {
1380         local _MSG_CURRENT_STAGE_general
1381         _MSG_CURRENT_STAGE_general="deinstallation of obsolete/leaf packages"
1382         temp_set_msg_current_stage "${_MSG_CURRENT_STAGE_general}"
1383         message_section_title "Deinstallation of unused obsolete/leaf packages"
1384         program_exec_restartable_loop_operation ports_to_delete
1385         temp_set_msg_current_stage
1386         message_echo
1387 }
1388 program_exec_and_record_completion DEINST_UNUSED_PKGS
1389
1390 # Clean up obsolete or unused distfiles
1391 if [ $opt_only_target_scope = no -a $opt_keep_distfiles = no ]
1392 then
1393         PROGRAM_DEPENDS='REINSTALLATION DISTFILES_LIST'
1394         _program_exec_and_record_completion__operation ()
1395         {
1396                 local tmp_distfiles_exists
1397                 message_section_title "Cleaning up obsolete or unused distfiles"
1398                 tmp_distfiles_exists=${TMPDIR}/CLEANUP_OBSLETE_DISTFILES::distfiles_exists
1399                 [ $opt_dry_run = yes ] && message_echo "INFO: The operations are not actually carried out."
1400                 ( set -e; cd "${DISTDIR}" && find . -type f ) \
1401                         | sed 's|^\./||' | sort -u > $tmp_distfiles_exists
1402                 fileedit_manipulate_old_lines "$tmp_distfiles_exists" "${DBDIR}/distfiles.entire" \
1403                         | while read distfile
1404                 do
1405                         if [ $opt_batch_mode = no ]
1406                         then
1407                                 echo "  $distfile"
1408                         fi
1409                         [ $opt_dry_run = yes ] && continue
1410                         rm -f "${DISTDIR}/$distfile"
1411                 done
1412                 message_echo
1413         }
1414         program_exec_and_record_completion CLEANUP_OBSLETE_DISTFILES
1415 fi
1416
1417 # Rebuild of package database
1418 PROGRAM_DEPENDS='REINSTALLATION RESTORE_ONCE_DEINST_PKGS DEINST_UNUSED_PKGS'
1419 _program_exec_and_record_completion__operation ()
1420 {
1421         which -s pkgdb || return 0
1422         message_section_title "Rebuilding package database for portupgrade"
1423         pkgdb -fu
1424         message_echo
1425 }
1426 program_exec_and_record_completion REBUILD_PKGDB
1427
1428
1429 # ==================================================
1430 # ================ ENDING MESSAGES =================
1431 # ==================================================
1432
1433 # Notice of failures
1434 exists_unresolved_ports=
1435 message_summary_dependents_of_failed_reinstallation failure || exists_unresolved_ports=y
1436 message_summary_dependents_of_failed_reinstallation redo || exists_unresolved_ports=y
1437 message_summary_dependents_of_failed_reinstallation conflict || exists_unresolved_ports=y
1438 [ -n "$exists_unresolved_ports" ] && message_summary_advice_on_manual_solution
1439
1440 # End
1441 temp_terminate_process () { :; }
1442
1443 if [ -z "$exists_unresolved_ports" ]
1444 then
1445         message_section_title "COMPLETELY DONE"
1446         message_echo "- E N D -"
1447 else
1448         message_warn_no_achieved_progress || :
1449         message_section_title "Done with some unresolved problems"
1450         message_echo "- To be continued -"
1451 fi