OSDN Git Service

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