OSDN Git Service

Version 3.0.5+toward_3.1.0_20140708112157
[portsreinstall/current.git] / bin / portsreinstall
1 #!/bin/sh -e
2 # ==================================================================================
3 # portsreinstall main script
4 # Copyright (C) 2010-2014 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.1.0
16 # COMPATIBLE_VERSIONS='^(3\.1\.[0-9]+)$'
17 # Template for development versions
18 MYVERSION=3.0.5+toward_3.1.0_20140708112157
19 COMPATIBLE_VERSIONS='^(3\.0\.[0-9]+\+toward_3\.1\.[0-9]+_[0-9]+|3\.0\.[0-9]+\+toward_3\.0\.[0-9]+_[0-9]+|3\.1\.[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         message_section_title "Collecting all installed packages"
304         pkg_info_qoa > ${DBDIR}/installed_ports
305         pkg_info_gen_pkg_origin_table
306         str_escape_regexp_filter < "${DBDIR}/installed_ports" \
307                 | sed 's/^/^/; s/$/$/' > ${DBDIR}/installed_ports.grep_pattern
308         message_echo
309 }
310 program_exec_and_record_completion COLLECT_ALL_INSTALLED_PACKAGES
311
312 # Preliminary inspection of tools which have to be up-to-date
313 # (No need depend on PARSE_CONF because INSPECT_ALL_DEPENDENCIES will take the task.)
314 PROGRAM_DEPENDS=
315 _program_exec_restartable_loop_operation__routine ()
316 {
317         local origin
318         origin=$1
319         database_build_inspect_dependencies "$origin"
320 }
321 _program_exec_and_record_completion__operation ()
322 {
323         local DEPTH_INDEX
324         message_section_title "Preliminary inspection of tools which have to be up-to-date"
325         {
326                 [ "$PKGSYS_USE_PKGNG" = yes ] && echo 'ports-mgmt/pkg'
327                 pkgsys_is_dialog4ports_used && echo 'ports-mgmt/dialog4ports'
328                 [ -n "$MYPORTORIGIN" ] && echo "$MYPORTORIGIN"
329         } 2> /dev/null > ${DBDIR}/stage.loop_list/tools_to_inspect
330         DEPTH_INDEX='--'
331         program_exec_restartable_loop_operation tools_to_inspect
332         database_build_post_inspect_dependencies
333         message_echo
334 }
335 program_exec_and_record_completion PRELIMINARY_INSPECTION_OF_TOOLS
336
337 # Upgrade of ports-mgmt/pkg if new
338 # (No need depend on PARSE_CONF because REINSTALLATION will take the task.)
339 if [ \( "$COMMAND_MODE" = do -o "$COMMAND_MODE" = redo \) \
340         -a $opt_dry_run = no -a $opt_suppress_pkgtools_upadte = no \
341         -a "$PKGSYS_USE_PKGNG" = yes ]
342 then
343         PROGRAM_DEPENDS='PRELIMINARY_INSPECTION_OF_TOOLS'
344         _program_exec_and_record_completion__operation ()
345         {
346                 local _MSG_CURRENT_STAGE_general
347                 _MSG_CURRENT_STAGE_general="pkgng upgrade"
348                 temp_set_msg_current_stage "${_MSG_CURRENT_STAGE_general}"
349                 message_section_title "Upgrade of ports-mgmt/pkg if new"
350                 touch "${DBDIR}/target_all"
351                 reinstall_exec ports-mgmt/pkg
352                 reinstall_restore_conflicts
353                 rm -f "${DBDIR}/target_all"
354                 temp_set_msg_current_stage
355                 message_echo
356         }
357         program_exec_and_record_completion UPGRADE_PKGNG
358 fi
359
360 # Upgrade of ports-mgmt/dialog4ports if new
361 # (No need depend on PARSE_CONF because REINSTALLATION will take the task.)
362 if [ \( "$COMMAND_MODE" = do -o "$COMMAND_MODE" = redo \) \
363         -a $opt_dry_run = no -a $opt_suppress_pkgtools_upadte = no ] \
364         && pkgsys_is_dialog4ports_used
365 then
366         PROGRAM_DEPENDS='PRELIMINARY_INSPECTION_OF_TOOLS'
367         _program_exec_and_record_completion__operation ()
368         {
369                 local _MSG_CURRENT_STAGE_general
370                 _MSG_CURRENT_STAGE_general="pkgng dialog4ports"
371                 temp_set_msg_current_stage "${_MSG_CURRENT_STAGE_general}"
372                 message_section_title "Upgrade of dialog4ports if new"
373                 touch "${DBDIR}/target_all"
374                 reinstall_exec ports-mgmt/dialog4ports
375                 reinstall_restore_conflicts
376                 rm -f "${DBDIR}/target_all"
377                 temp_set_msg_current_stage
378                 message_echo
379         }
380         program_exec_and_record_completion UPGRADE_DIALOG4PORTS
381 fi
382
383 # Upgrade of this utility if new
384 # (No need depend on PARSE_CONF because REINSTALLATION will take the task.)
385 if [ \( "$COMMAND_MODE" = do -o "$COMMAND_MODE" = redo \) \
386         -a $opt_dry_run = no -a $opt_suppress_self_upadte = no \
387         -a -n "$MYPORTORIGIN" ]
388 then
389         PROGRAM_DEPENDS='PRELIMINARY_INSPECTION_OF_TOOLS'
390         _program_exec_and_record_completion__operation ()
391         {
392                 local _MSG_CURRENT_STAGE_general
393                 _MSG_CURRENT_STAGE_general="pkgng upgrade"
394                 temp_set_msg_current_stage "${_MSG_CURRENT_STAGE_general}"
395                 message_section_title "Upgrade of this utility if new"
396                 touch "${DBDIR}/target_all"
397                 reinstall_exec "$MYPORTORIGIN"
398                 reinstall_restore_conflicts
399                 rm -f "${DBDIR}/target_all"
400                 temp_set_msg_current_stage
401                 message_echo
402         }
403         program_exec_and_record_completion UPGRADE_SELF
404 fi
405
406 if [ "x`${APPNAME} -aV 2> /dev/null`" != "x$MYVERSION" ]
407 then
408         message_echo "INFO: ${APPNAME} is upgraded and the temporary database needs refresh."
409         database_build_clean_for_self_upgrade || :
410         message_echo "INFO: Restarting with the new version."
411         message_echo
412         temp_trap_for_invoking_new_version
413         . "${TMPDIR}"/restart_command.sh
414         exit
415 fi
416
417
418 # ==================================================
419 # ================== PREPARATION ===================
420 # ==================================================
421
422 # ============= Correspondence to configuration changes =============
423
424 # Patch to the temporary database by reflecting changes in configuration
425 PROGRAM_DEPENDS='PARSE_CONF'
426 _program_exec_and_record_completion__operation ()
427 {
428         local tmpfile_diff tmpfile_old tmpfile_new key
429         [ -d "${DBDIR}/conf.prev" ] || return 0
430         message_section_title "Patch to the temporary database by reflecting changes in configuration"
431         tmpfile_old=${TMPDIR}/PATCH_TO_TMPDB_REFLECT_CONF_CHANGES::old
432         tmpfile_new=${TMPDIR}/PATCH_TO_TMPDB_REFLECT_CONF_CHANGES::new
433         tmpfile_updated_ports=${TMPDIR}/PATCH_TO_TMPDB_REFLECT_CONF_CHANGES::updated_ports
434         if fileedit_manipulate_old_new_lines \
435                 "${DBDIR}/conf.prev/setenv.sh" "${DBDIR}/conf/setenv.sh" "$tmpfile_old" "$tmpfile_new"
436         then
437                 if grep -q -e ^LOCALBASE= -e ^LINUXBASE= -e ^PORTSDIR= "$tmpfile_old" "$tmpfile_new"
438                 then
439                         message_echo "ERROR: Migration of the temporary database is unavailable because LOCALBASE, LINUXBASE or PORTSDIR was changed." >&2
440                         message_echo "        ${APPNAME} clean" >&2
441                         message_echo "must be executed in advance." >&2
442                         exit 1
443                 fi
444         fi
445         cut -s -d '|' -f 1,2 "${DBDIR}/conf.prev/MOVED_ALT.parsed" | tr '|' '\t' > ${TMPDIR}/MOVED_ALT.old
446         cut -s -d '|' -f 1,2 "${DBDIR}/conf/MOVED_ALT.parsed" | tr '|' '\t' > ${TMPDIR}/MOVED_ALT.new
447         if fileedit_manipulate_old_new_lines \
448                 "${TMPDIR}/MOVED_ALT.old" "${TMPDIR}/MOVED_ALT.new" "$tmpfile_old" "$tmpfile_new"
449         then
450                 cat "$tmpfile_old" "$tmpfile_new" | while read from to
451                 do
452                         echo "$from"
453                         [ -n "$to" ] && echo "$to"
454                 done
455         fi > $tmpfile_updated_ports
456         if fileedit_manipulate_old_new_lines \
457                 "${DBDIR}/conf.prev/REPLACE.csv" "${DBDIR}/conf/REPLACE.csv" "$tmpfile_old" "$tmpfile_new"
458         then
459                 cat "$tmpfile_old" "$tmpfile_new" | while read from to
460                 do
461                         echo "$from"
462                         [ -n "$to" ] && echo "$to"
463                 done
464         fi >> $tmpfile_updated_ports
465         [ `wc -l < $tmpfile_updated_ports` -gt 0 ] && rm -f "${DBDIR}/REPLACE.complete_sed_pattern"
466         [ -d "${DBDIR}/conf/each_port" ] && find "${DBDIR}/conf/each_port" -depth 2 \
467                 | while read dbpath
468         do
469                 origin=`str_dirpath_to_origin "$dbpath"`
470                 dbpath_prev=${DBDIR}/conf.prev/each_port/$origin
471                 diff -r "$dbpath_prev" "$dbpath" > /dev/null 2>&1 && continue
472                 echo "$origin"
473         done >> $tmpfile_updated_ports
474         [ -d "${DBDIR}/conf.prev/each_port" ] && find "${DBDIR}/conf.prev/each_port" -depth 2 \
475                 | while read dbpath_prev
476         do
477                 origin=`str_dirpath_to_origin "$dbpath_prev"`
478                 dbpath=${DBDIR}/conf/each_port/$origin
479                 [ -d "$dbpath" ] && continue
480                 echo "$origin"
481         done >> $tmpfile_updated_ports
482         if [ `wc -l < $tmpfile_updated_ports` -gt 0 ]
483         then
484                 sort -u "$tmpfile_updated_ports" | while read origin
485                 do
486                         database_build_patch_reconf "$origin"
487                 done
488                 program_deregister_stage_complete INSPECT_ALL_DEPENDENCIES
489         fi
490         message_echo
491 }
492 program_exec_and_record_completion PATCH_TO_TMPDB_REFLECT_CONF_CHANGES
493
494 # ============= Database construction =============
495
496 # Execute command operations which must be done before building the temporary database
497 command_exec_before_building_tempdb "$@"
498
499 # Meta process for redo
500 PROGRAM_DEPENDS=''
501 _program_exec_and_record_completion__operation ()
502 {
503         rm -f "${DBDIR}/new_success_in_current_run"
504         [ "x$COMMAND_MODE" = xredo ] || return 0
505         message_echo "[REDO mode]"
506         message_echo
507 }
508 program_exec_and_record_completion REDO_INIT
509
510 # Determine specified targets
511 PROGRAM_DEPENDS=''
512 _program_exec_and_record_completion__operation ()
513 {
514         local tag level dbsuffix
515         message_section_title "Determining specified targets"
516         cat "${DBDIR}/stage.loop_list/target_itself.specified" \
517                 "${DBDIR}/stage.loop_list/target_dependents.specified" \
518                 "${DBDIR}/stage.loop_list/target_requirements.specified" \
519                 "${DBDIR}/need.list" \
520                 "${DBDIR}/targets_specified_so_far" 2> /dev/null \
521                 | sort -u > ${DBDIR}/targets_specified_so_far.tmp
522         mv "${DBDIR}/targets_specified_so_far.tmp" "${DBDIR}/targets_specified_so_far"
523         rm -f "${DBDIR}/stage.loop_list/target_itself.specified" \
524                 "${DBDIR}/stage.loop_list/target_dependents.specified" \
525                 "${DBDIR}/stage.loop_list/target_requirements.specified"
526         if [ -n "$opt_target_itself$opt_target_dependents$opt_target_requirements" ]
527         then
528                 options_select_new_ports_if_duplicated O \
529                         "${DBDIR}/stage.loop_list/target_itself.specified" "$opt_target_itself"
530                 options_select_new_ports_if_duplicated t \
531                         "${DBDIR}/stage.loop_list/target_dependents.specified" "$opt_target_dependents"
532                 options_select_new_ports_if_duplicated T \
533                         "${DBDIR}/stage.loop_list/target_requirements.specified" "$opt_target_requirements"
534                 if [ `cat "${DBDIR}/stage.loop_list/target_itself.specified" \
535                         "${DBDIR}/stage.loop_list/target_dependents.specified" \
536                         "${DBDIR}/stage.loop_list/target_requirements.specified" | wc -l` -eq 0 ]
537                 then
538                         message_echo "ERROR: No matching port for target globs." >&2
539                         message_echo >&2
540                         exit 1
541                 fi
542                 cat "${DBDIR}/stage.loop_list/target_itself.specified" \
543                         "${DBDIR}/stage.loop_list/target_dependents.specified" \
544                         "${DBDIR}/stage.loop_list/target_requirements.specified" \
545                         | sort -u > ${TMPDIR}/DETERMINE_SPECIFIED_TARGETS.reset
546                 cat "${TMPDIR}/DETERMINE_SPECIFIED_TARGETS.reset" "${DBDIR}/need.list" 2> /dev/null \
547                         | sort -u > ${DBDIR}/need.list.tmp
548                 mv "${DBDIR}/need.list.tmp" "${DBDIR}/need.list"
549                 sort -u "${DBDIR}/need.list" "${DBDIR}/targets_specified_so_far" \
550                         > ${DBDIR}/targets_specified_so_far.tmp
551                 mv "${DBDIR}/targets_specified_so_far.tmp" "${DBDIR}/targets_specified_so_far"
552                 for tag in all run build none
553                 do
554                         for level in direct full
555                         do
556                                 dbsuffix=$tag.$level
557                                 {
558                                         cat "${TMPDIR}/DETERMINE_SPECIFIED_TARGETS.reset"
559                                         cat "${DBDIR}/stage.loop_list/target_dependents.specified" | while read origin
560                                         do
561                                                 nodedir=${DBDIR}/requires/$origin
562                                                 cat "$nodedir/dependents.$dbsuffix" 2> /dev/null
563                                         done
564                                         cat "${DBDIR}/stage.loop_list/target_requirements.specified" | while read origin
565                                         do
566                                                 nodedir=${DBDIR}/requires/$origin
567                                                 cat "$nodedir/requirements.$dbsuffix" 2> /dev/null
568                                         done
569                                 } | sort -u | while read origin
570                                 do
571                                         fileedit_rm_a_line "$origin" "${DBDIR}/success.$dbsuffix.list"
572                                         fileedit_rm_a_line "$origin" "${DBDIR}/todo_after_requirements_succeed.$dbsuffix.list"
573                                         rm -f "${DBDIR}/requires/$origin/succeeded_once"
574                                 done
575                         done
576                 done
577         fi
578         message_echo
579 }
580 program_exec_and_record_completion DETERMINE_SPECIFIED_TARGETS
581
582 # Show specified targets
583 if [ -n "$opt_target_itself$opt_target_dependents$opt_target_requirements" -a $opt_batch_mode = no ]
584 then
585         message_echo "INFO: (Re/de-)installation will be carried out only for the targets:"
586         echo
587         if [ `wc -l < ${DBDIR}/stage.loop_list/target_itself.specified` -gt 0 ]
588         then
589                 message_echo "[Targets only]"
590                 echo "----------------------------------------"
591                 cat "${DBDIR}/stage.loop_list/target_itself.specified"
592                 echo "----------------------------------------"
593                 echo
594         fi
595         if [ `wc -l < ${DBDIR}/stage.loop_list/target_dependents.specified` -gt 0 ]
596         then
597                 message_echo "[Targets with their `options_get_dependency_msgterm` dependents]"
598                 echo "----------------------------------------"
599                 cat "${DBDIR}/stage.loop_list/target_dependents.specified"
600                 echo "----------------------------------------"
601                 echo
602         fi
603         if [ `wc -l < ${DBDIR}/stage.loop_list/target_requirements.specified` -gt 0 ]
604         then
605                 message_echo "[Targets with their `options_get_dependency_msgterm` requirements]"
606                 echo "----------------------------------------"
607                 cat "${DBDIR}/stage.loop_list/target_requirements.specified"
608                 echo "----------------------------------------"
609                 echo
610         fi
611 fi
612
613 # Determine all target ports
614 PROGRAM_DEPENDS='DETERMINE_SPECIFIED_TARGETS COLLECT_ALL_INSTALLED_PACKAGES'
615 _program_exec_and_record_completion__operation ()
616 {
617         message_section_title "Determining all target ports"
618         {
619                 if [ $opt_only_target_scope = no ]
620                 then
621                         cat "${DBDIR}/installed_ports" 2> /dev/null || :
622                 fi
623                 cat "${DBDIR}/stage.loop_list/target_itself.specified" || :
624                 cat "${DBDIR}/stage.loop_list/target_dependents.specified" || :
625                 cat "${DBDIR}/stage.loop_list/target_requirements.specified" || :
626                 cat "${DBDIR}/targets_specified_so_far" || :
627         }  2> /dev/null | sort -u > "${DBDIR}/stage.loop_list/ports_to_inspect"
628         message_echo
629 }
630 program_exec_and_record_completion DETERMINE_ALL_TARGET_PORTS
631
632 # Inspection of all dependencies
633 PROGRAM_DEPENDS='PARSE_CONF DETERMINE_ALL_TARGET_PORTS'
634 _program_exec_restartable_loop_operation__routine ()
635 {
636         local origin
637         origin=$1
638         database_build_inspect_dependencies "$origin"
639 }
640 _program_exec_and_record_completion__operation ()
641 {
642         local DEPTH_INDEX 
643         message_section_title "Inspecting dependencies of the all installed packages"
644         [ $opt_only_target_scope = no -a -n "$opt_target_itself$opt_target_dependents$opt_target_requirements" ] && \
645                 message_echo "INFO: Ports which seem irrelevant to the targets are also inspected in order to get complete information."
646         DEPTH_INDEX='--'
647         program_exec_restartable_loop_operation ports_to_inspect
648         database_build_post_inspect_dependencies
649         message_echo
650 }
651 program_exec_and_record_completion INSPECT_ALL_DEPENDENCIES
652
653 # Convert dependency-lists to actual ones
654 PROGRAM_DEPENDS='INSPECT_ALL_DEPENDENCIES'
655 _program_exec_restartable_loop_operation__routine ()
656 {
657         local origin table dbtag level tag target
658         origin=$1
659         for table in dependents requirements
660         do
661                 for dbtag in requires obsolete
662                 do
663                         for level in direct full
664                         do
665                                 for tag in all run build
666                                 do
667                                         target=${DBDIR}/$dbtag/$origin/${table}.${tag}.${level}
668                                         if [ -e "$target.src" ]
669                                         then
670                                                 sed -E -f "${DBDIR}/REPLACE.complete_sed_pattern" "$target.src" \
671                                                         | grep -v '^$' | sort -u > $target.tmp
672                                                 [ -e "$target" ] && ! diff "$target.tmp" "$target" > /dev/null \
673                                                         && echo "$origin" >> ${DBDIR}/update_dependencies
674                                                 mv "$target.tmp" "$target"
675                                         else
676                                                 [ -e "$target" ] && echo "$origin" >> ${DBDIR}/update_dependencies
677                                                 rm -f "$target"
678                                         fi
679                                 done
680                         done
681                 done
682         done
683 }
684 _program_exec_and_record_completion__operation ()
685 {
686         message_section_title "Conversion of dependency-lists to actual ones"
687         program_exec_restartable_loop_operation convert_dependency_lists
688         sort -u "${DBDIR}/update_dependencies" > ${DBDIR}/update_dependencies.tmp
689         mv "${DBDIR}/update_dependencies.tmp" "${DBDIR}/update_dependencies"
690         str_escape_regexp_filter < ${DBDIR}/update_dependencies \
691                 | sed 's/^/^/; s/$/$/' > ${DBDIR}/update_dependencies.grep_pattern
692         for tag in all run build
693         do
694                 ( cd "${DBDIR}/requires" && \
695                         find . -depth 3 -type f -name requirements.${tag}.full -or -name requirements.${tag}.full.orig ) \
696                         | sort -u \
697                         | sed 's|^./||;s|/[^/]*$||' \
698                         | grep -v -E -f "${DBDIR}/update_dependencies.grep_pattern" \
699                         | str_escape_regexp_filter | sed 's/^/^/; s/$/$/' \
700                         > ${TMPDIR}/convert_requirements_list:full_complete.grep_pattern || :
701                 ( cd "${DBDIR}/requires" && \
702                         find . -depth 3 -type f -name requirements.${tag}.direct -or -name requirements.${tag}.direct.orig ) \
703                         | sort -u \
704                         | sed 's|^./||;s|/[^/]*$||' \
705                         | grep -v -E -f "${TMPDIR}/convert_requirements_list:full_complete.grep_pattern" \
706                         > ${DBDIR}/stage.loop_list/complete_recursive_${tag}time_reqlists || :
707         done
708         for inspected_level_tmp in direct node
709         do
710                 cat "${DBDIR}/ports.inspected.${inspected_level_tmp}.list" || :
711         done 2> /dev/null | sort -u > ${DBDIR}/stage.loop_list/trim_dependency_lists_rm_uninspected_ports
712         find "${DBDIR}/requires" -depth 2 -type d > ${DBDIR}/stage.loop_list/inspect_dependent
713         [ -e "${DBDIR}/dependents_files" ] && \
714                 mv "${DBDIR}/dependents_files" "${DBDIR}/dependents_files.prev"
715         rm -f "${DBDIR}/stage.loop_list/make_dependents_lists_unique.tmp" "${DBDIR}/dependents_files.tmp"
716         message_echo
717 }
718 program_exec_and_record_completion CONVERT_REQUIREMENTS_LIST
719
720 # Completion of recursive requirement lists
721 for _REQUIREMENT_LISTS_tag in all run build
722 do
723         PROGRAM_DEPENDS='CONVERT_REQUIREMENTS_LIST'
724         _program_exec_restartable_loop_operation__routine ()
725         {
726                 local tag dbpath origin suffix
727                 tag=${_REQUIREMENT_LISTS_tag}
728                 dbpath=$1
729                 origin=`str_dirpath_to_origin "$dbpath"`
730                 for suffix in '' .orig
731                 do
732                         database_build_get_complete_recursive_dependency requirements.${tag} "$origin" "$suffix" > /dev/null
733                 done
734         }
735         _program_exec_and_record_completion__operation ()
736         {
737                 local tag
738                 tag=${_REQUIREMENT_LISTS_tag}
739                 message_section_title "Completion of ${tag}-time requirement lists"
740                 program_exec_restartable_loop_operation complete_recursive_${tag}time_reqlists
741                 message_echo
742         }
743         program_exec_and_record_completion RECURSIVE_REQUIREMENT_LISTS:${_REQUIREMENT_LISTS_tag}
744 done
745
746 # Trim dependency lists by removing uninspected ports
747 if [ $opt_only_target_scope = yes ]
748 then
749         PROGRAM_DEPENDS='INSPECT_ALL_DEPENDENCIES CONVERT_REQUIREMENTS_LIST'
750         _program_exec_restartable_loop_operation__routine ()
751         {
752                 local dbpath tag level srcdb
753                 dbpath=$1
754                 for tag in all run build
755                 do
756                         for level in direct full
757                         do
758                                 srcdb=requirements.${tag}.${level}
759                                 [ -e "$dbpath/$srcdb" ] || continue
760                                 grep -E -f "${DBDIR}/inspected_ports.grep_pattern" "$dbpath/$srcdb" \
761                                         > $dbpath/$srcdb.tmp || :
762                                 mv "$dbpath/$srcdb.tmp" "$dbpath/$srcdb"
763                         done
764                 done
765         }
766         _program_exec_and_record_completion__operation ()
767         {
768                 message_section_title "Trimming dependency lists by removing uninspected ports"
769                 program_exec_restartable_loop_operation trim_dependency_lists_rm_uninspected_ports
770                 message_echo
771         }
772         program_exec_and_record_completion TRIM_DEPENDENCY_LISTS_RM_UNINSPECTED_PORTS
773 fi
774
775 # Inspection of dependents
776 PROGRAM_DEPENDS='INSPECT_ALL_DEPENDENCIES CONVERT_REQUIREMENTS_LIST TRIM_DEPENDENCY_LISTS_RM_UNINSPECTED_PORTS'
777 _program_exec_restartable_loop_operation__routine ()
778 {
779         local dbpath origin tag level suffix srcdb dstdb
780         dbpath=$1
781         origin=`str_dirpath_to_origin "$dbpath"`
782         for tag in all run build
783         do
784                 for level in direct full
785                 do
786                         for suffix in '' .orig
787                         do
788                                 srcdb=requirements.${tag}.${level}${suffix}
789                                 dstdb=dependents.${tag}.${level}${suffix}
790                                 [ -e "$dbpath/$srcdb" ] || continue
791                                 while read origin_requirement
792                                 do
793                                         dstpath=${DBDIR}/requires/$origin_requirement
794                                         echo "$dstpath/$dstdb" >> ${DBDIR}/dependents_files.tmp
795                                         [ "$dstpath/$dstdb" -nt "$dbpath/$srcdb" ] && continue
796                                         [ -d "$dstpath" ] || mkdir -p "$dstpath"
797                                         echo "$origin" >> $dstpath/$dstdb.raw
798                                         echo "$dstpath/$dstdb" >> ${DBDIR}/stage.loop_list/make_dependents_lists_unique.tmp
799                                 done < $dbpath/$srcdb
800                         done
801                 done
802         done
803 }
804 _program_exec_and_record_completion__operation ()
805 {
806         local dbrequires_valesc
807         message_section_title "Inspection of dependents"
808         dbrequires_valesc=`str_escape_replaceval "${DBDIR}/requires/"`
809         program_exec_restartable_loop_operation inspect_dependent
810         sort -u "${DBDIR}/stage.loop_list/make_dependents_lists_unique.tmp" 2> /dev/null \
811                 > ${DBDIR}/stage.loop_list/make_dependents_lists_unique || :
812         sort -u "${DBDIR}/dependents_files.tmp" 2> /dev/null > ${DBDIR}/dependents_files || :
813         [ -e "${DBDIR}/make_dependents_lists_unique.prev" ] && \
814                 fileedit_manipulate_old_lines "${DBDIR}/dependents_files.prev" "${DBDIR}/dependents_files" \
815                 | xargs rm -f
816         message_echo
817 }
818 program_exec_and_record_completion INSPECT_DEPENDENTS
819
820 # Remove duplicated lines in dependents lists
821 PROGRAM_DEPENDS='CONVERT_REQUIREMENTS_LIST INSPECT_DEPENDENTS'
822 _program_exec_restartable_loop_operation__routine ()
823 {
824         local dbpath tag level dstdb
825         dstdb=$1
826         cat "$dstdb" "$dstdb.raw" 2> /dev/null | sort -u > $dstdb.tmp
827         mv "$dstdb.tmp" "$dstdb"
828         rm -f "$dstdb.raw"
829 }
830 _program_exec_and_record_completion__operation ()
831 {
832         local dbrequires_valesc
833         message_section_title "Removing duplicated items in dependents lists"
834         program_exec_restartable_loop_operation make_dependents_lists_unique
835         message_echo
836 }
837 program_exec_and_record_completion MAKE_DEPENDENTS_LISTS_UNIQUE
838
839 # Preparation of target attribute information
840 for _TARGET_ATTR_INFO_table in requirements dependents itself
841 do
842         [ `cat "${DBDIR}/stage.loop_list/target_${_TARGET_ATTR_INFO_table}.replaced.specified" 2> /dev/null \
843                 | wc -l` -gt 0 ] || continue
844         PROGRAM_DEPENDS='DETERMINE_SPECIFIED_TARGETS CONVERT_REQUIREMENTS_LIST'
845         _program_exec_restartable_loop_operation__routine ()
846         {
847                 local origin dbtargets_valesc table
848                 origin=$1
849                 dbtargets_valesc=`str_escape_replaceval "${DBDIR}/targets/"`
850                 table=${_TARGET_ATTR_INFO_table}
851                 for database in requires initial
852                 do
853                         dbpath=${DBDIR}/$database/$origin
854                         dstpath=${DBDIR}/targets/$origin
855                         [ -d "$dstpath" ] || mkdir -p "$dstpath"
856                         touch "$dstpath/target_itself"
857                         echo "$origin" >> ${DBDIR}/all_targets.lst
858                         [ $table = itself ] && continue
859                         for tag in all run build
860                         do
861                                 for level in direct full
862                                 do
863                                         srcdb=${table}.${tag}.${level}
864                                         dstdb=target_${database}_${table}.${tag}.${level}
865                                         [ -e "$dbpath/$srcdb" ] || continue
866                                         cat "$dbpath/$srcdb" >> ${DBDIR}/all_targets.lst
867                                         sed -E "s/^/$dbtargets_valesc/; s|$|/$dstdb|" "$dbpath/$srcdb" \
868                                                 | fileedit_add_a_line_to_files_if_new "$origin"
869                                 done
870                         done
871                 done
872         }
873         _program_exec_and_record_completion__operation ()
874         {
875                 local table
876                 table=${_TARGET_ATTR_INFO_table}
877                 message_section_title "Preparation of target attribute information for dependency [$table]"
878                 program_exec_restartable_loop_operation target_$table.replaced.specified
879                 message_echo
880         }
881         program_exec_and_record_completion TARGET_ATTR_INFO:${_TARGET_ATTR_INFO_table}
882 done
883
884 # Post-process after the preparation of target attribute information
885 PROGRAM_DEPENDS='MAKE_DEPENDENTS_LISTS_UNIQUE TARGET_ATTR_INFO:requirements TARGET_ATTR_INFO:dependents'
886 _program_exec_and_record_completion__operation ()
887 {
888         message_section_title "Post-process after the preparation of target attribute information"
889         sort -u "${DBDIR}/all_targets.lst" 2> /dev/null \
890                 | grep -E -f "${DBDIR}/inspected_ports.grep_pattern" \
891                 | sed -E -f "${DBDIR}/REPLACE.complete_sed_pattern" \
892                 > ${DBDIR}/all_targets.lst.tmp || :
893         mv "${DBDIR}/all_targets.lst.tmp" "${DBDIR}/all_targets.lst"
894         find "${DBDIR}/targets" -depth 2 -type d > ${DBDIR}/stage.loop_list/build_complement_to_new_dependents_for_targets 2> /dev/null || :
895         {
896                 cat "${DBDIR}/all_targets.lst" "${DBDIR}/need.with_replaced.list" 2> /dev/null || :
897                 find "${DBDIR}/requires" -depth 3 -type f -name installed_version \
898                         | sed -E 's|.*/([^/]+/[^/]+)/[^/]*$|\1|'
899         } | sort -u > ${DBDIR}/stage.loop_list/inspect_necessity
900         cp /dev/null "${DBDIR}/stage.loop_list/parse_target_attr_info"
901         find -E "${DBDIR}/requires" -depth 3 -type f -regex '.*/necessary_port\.(direct|full)$' -delete
902         message_echo
903 }
904 program_exec_and_record_completion TARGET_ATTR_INFO_POSTPROCESS
905
906 # Build of data on complement to new dependents for target attribute information
907 PROGRAM_DEPENDS='TARGET_ATTR_INFO_POSTPROCESS TARGET_ATTR_INFO:requirements TARGET_ATTR_INFO:dependents CONVERT_REQUIREMENTS_LIST'
908 _program_exec_restartable_loop_operation__routine ()
909 {
910         local dbpath origin
911         dbpath=$1
912         origin=`str_dirpath_to_origin "$dbpath"`
913         database_build_complement_to_new_dependents_for_targets "$origin"
914 }
915 _program_exec_and_record_completion__operation ()
916 {
917         message_section_title "Build of data on complement to new dependents for target attribute information"
918         program_exec_restartable_loop_operation build_complement_to_new_dependents_for_targets
919         sort -u "${DBDIR}/stage.loop_list/parse_target_attr_info" > ${DBDIR}/stage.loop_list/parse_target_attr_info.tmp
920         mv "${DBDIR}/stage.loop_list/parse_target_attr_info.tmp" "${DBDIR}/stage.loop_list/parse_target_attr_info"
921         message_echo
922 }
923 program_exec_and_record_completion COMPLEMENT_TO_NEW_DEPENDENTS_FOR_TARGET_ATTR_INFO
924
925 # Parse target attribute information
926 PROGRAM_DEPENDS='COMPLEMENT_TO_NEW_DEPENDENTS_FOR_TARGET_ATTR_INFO'
927 _program_exec_restartable_loop_operation__routine ()
928 {
929         local dbpath origin
930         dbpath=$1
931         origin=`str_dirpath_to_origin "$dbpath"`
932         database_build_target_attributes "$origin"
933 }
934 _program_exec_and_record_completion__operation ()
935 {
936         message_section_title "Parsing target attribute information"
937         program_exec_restartable_loop_operation parse_target_attr_info
938         message_echo
939 }
940 program_exec_and_record_completion PARSE_TARGET_ATTR_INFO
941
942 # Inspection of necessity
943 PROGRAM_DEPENDS='TARGET_ATTR_INFO_POSTPROCESS RECURSIVE_REQUIREMENT_LISTS:run RECURSIVE_REQUIREMENT_LISTS:build INSPECT_ALL_DEPENDENCIES'
944 _program_exec_restartable_loop_operation__routine ()
945 {
946         local origin
947         origin=$1
948         for level in direct full
949         do
950                 database_build_inspect_necessity_for_only_new_upgrade "$origin" "$level"
951         done
952 }
953 _program_exec_and_record_completion__operation ()
954 {
955         message_section_title "Inspection of necessity"
956         program_exec_restartable_loop_operation inspect_necessity
957         for level in direct full
958         do
959                 find "${DBDIR}/requires" -depth 3 -type f -name "necessary_port.${level}" \
960                         > ${DBDIR}/stage.loop_list/necessary_ports.${level}
961         done
962         message_echo
963 }
964 program_exec_and_record_completion INSPECT_NECESSITY
965
966 # Inspection of necessary upgrades
967 for _NECESSARY_UPDATES_level in direct full
968 do
969         PROGRAM_DEPENDS='INSPECT_NECESSITY INSPECT_ALL_DEPENDENCIES MAKE_DEPENDENTS_LISTS_UNIQUE'
970         _program_exec_restartable_loop_operation__routine ()
971         {
972                 local markerpath level dbpath origin tag
973                 markerpath=$1
974                 level=${_NECESSARY_UPDATES_level}
975                 dbpath=`dirname "$markerpath"`
976                 origin=`str_dirpath_to_origin "$dbpath"`
977                 database_query_does_a_port_need_update "$origin" || return 0
978                 for tag in all run build none
979                 do
980                         touch "$dbpath/necessary_upgrade.$tag.${level}"
981                         [ -e "$dbpath/dependents.$tag.${level}" ] || continue
982                         while read origin_dependent
983                         do
984                                 touch "${DBDIR}/requires/$origin_dependent/necessary_upgrade.$tag.${level}"
985                         done < $dbpath/dependents.$tag.${level}
986                 done
987         }
988         _program_exec_and_record_completion__operation ()
989         {
990                 local level
991                 level=${_NECESSARY_UPDATES_level}
992                 message_section_title "Inspection of necessary upgrades at the $level level"
993                 program_exec_restartable_loop_operation necessary_ports.${level}
994                 message_echo
995         }
996         program_exec_and_record_completion NECESSARY_UPDATES:${_NECESSARY_UPDATES_level}
997 done
998
999 # Preparation for inspection of new leaf ports
1000 if [ ! -e "${DBDIR}/inspected_ports_only_partially" ]
1001 then
1002         PROGRAM_DEPENDS='INSPECT_ALL_DEPENDENCIES MAKE_DEPENDENTS_LISTS_UNIQUE PARSE_CONF'
1003         _program_exec_and_record_completion__operation ()
1004         {
1005                 message_section_title "Preparation for inspection of new leaf ports"
1006                 find "${DBDIR}/requires" -depth 3 -type f -name dependents.all.full \
1007                         | sed -E 's|.*/([^/]+/[^/]+)/[^/]+$|\1|' \
1008                         | sort -u > ${TMPDIR}/PREPARE_INSPECT_LEAF_PORTS:nonleaf_ports
1009                 sort -u "${DBDIR}/inspected_ports" > ${TMPDIR}/PREPARE_INSPECT_LEAF_PORTS:inspected_ports
1010                 fileedit_manipulate_new_lines \
1011                         "${TMPDIR}/PREPARE_INSPECT_LEAF_PORTS:nonleaf_ports" \
1012                         "${TMPDIR}/PREPARE_INSPECT_LEAF_PORTS:inspected_ports" \
1013                         | grep -v -E -f "${DBDIR}/conf/HOLD_PORTS.grep_pattern" \
1014                         > ${DBDIR}/stage.loop_list/leaf_ports_primary_candidates || :
1015                 cp /dev/null "${DBDIR}/grep.leaf_ports.pattern"
1016                 cp /dev/null "${DBDIR}/stage.loop_list/leaf_ports_secondary_candidates"
1017                 message_echo
1018         }
1019         program_exec_and_record_completion PREPARE_INSPECT_LEAF_PORTS
1020 fi
1021
1022 # Inspection of new primary leaf ports
1023 if [ ! -e "${DBDIR}/inspected_ports_only_partially" ]
1024 then
1025         PROGRAM_DEPENDS='INSPECT_ALL_DEPENDENCIES MAKE_DEPENDENTS_LISTS_UNIQUE PREPARE_INSPECT_LEAF_PORTS PARSE_CONF'
1026         _program_exec_restartable_loop_operation__routine ()
1027         {
1028                 local origin origin_ini origin_esc dbpath origin_req
1029                 origin=$1
1030                 pkgsys_is_pkgtool "$origin" && return
1031                 dbpath=${DBDIR}/requires/$origin
1032                 origin_esc=`str_escape_regexp "$origin"`
1033                 grep -q -E "^$origin_esc$" "${DBDIR}/need.with_replaced.list" 2> /dev/null && return
1034                 if ! grep -q -E "^$origin_esc$" "${DBDIR}/noneed.list" 2> /dev/null
1035                 then
1036                         if [ -e "$dbpath/initial_orig" ]
1037                         then
1038                                 origin_ini=`cat "$dbpath/initial_orig"`
1039                                 [ -e "${DBDIR}/initial/$origin_ini/installed_version" \
1040                                         -a `cat "${DBDIR}/initial/$origin_ini/dependents.all.full" 2> /dev/null | wc -l` -eq 0 ] \
1041                                         && return
1042                         fi
1043                         [ -e "${DBDIR}/initial/$origin/installed_version" \
1044                                 -a `cat "${DBDIR}/initial/$origin/dependents.all.full" 2> /dev/null | wc -l` -eq 0 ] \
1045                                 && return
1046                 fi
1047                 if [ -e "$dbpath/requirements.all.full" ]
1048                 then
1049                         grep -v -E -f "${DBDIR}/conf/HOLD_PORTS.grep_pattern" "$dbpath/requirements.all.full" | \
1050                                 fileedit_add_lines_if_new "${DBDIR}/stage.loop_list/leaf_ports_secondary_candidates" || :
1051                 fi
1052                 fileedit_add_a_line_if_new "^$origin_esc$" "${DBDIR}/grep.leaf_ports.pattern"
1053         }
1054         _program_exec_and_record_completion__operation ()
1055         {
1056                 local num_leaves num_leaves_prev
1057                 message_section_title "Inspection of new primary leaf ports"
1058                 program_exec_restartable_loop_operation leaf_ports_primary_candidates
1059                 wc -l < ${DBDIR}/grep.leaf_ports.pattern | tr -d ' ' > ${DBDIR}/num_leaves
1060                 cp /dev/null "${DBDIR}/leaf_ports_secondary_candidates.new_requirements"
1061                 message_echo "  `cat "${DBDIR}/num_leaves"` primary leaf port(s) is/are found."
1062                 message_echo
1063         }
1064         program_exec_and_record_completion INSPECT_PRIMARY_LEAF_PORTS
1065 fi
1066
1067 # Inspection of requirements of new leaf ports
1068 if [ ! -e "${DBDIR}/inspected_ports_only_partially" ]
1069 then
1070         PROGRAM_DEPENDS='INSPECT_ALL_DEPENDENCIES MAKE_DEPENDENTS_LISTS_UNIQUE INSPECT_PRIMARY_LEAF_PORTS PARSE_CONF'
1071         _program_exec_and_record_completion__operation ()
1072         {
1073                 local num_leaves num_leaves_prev num_inspect num_leaves_new
1074                 message_section_title "Inspection of requirements of new leaf ports"
1075                 message_echo "INFO: The inspection proceeds by iterative method."
1076                 while :
1077                 do
1078                         _program_exec_restartable_loop_operation__routine ()
1079                         {
1080                                 local origin origin_esc dbpath
1081                                 origin=$1
1082                                 pkgsys_is_pkgtool "$origin" && return
1083                                 dbpath=${DBDIR}/requires/$origin
1084                                 origin_esc=`str_escape_regexp "$origin"`
1085                                 grep -q -E "^$origin_esc$" "${DBDIR}/need.with_replaced.list" 2> /dev/null && return
1086                                 grep -E -v -f "${DBDIR}/grep.leaf_ports.pattern" \
1087                                         "$dbpath/dependents.all.full" > /dev/null 2>&1 && return
1088                                 cat "$dbpath/requirements.all.full" 2> /dev/null \
1089                                         >> ${DBDIR}/leaf_ports_secondary_candidates.new_requirements || :
1090                                 fileedit_add_a_line_if_new "^$origin_esc$" "${DBDIR}/grep.leaf_ports.pattern"
1091                         }
1092                         program_exec_restartable_loop_operation leaf_ports_secondary_candidates
1093                         num_leaves_prev=`cat "${DBDIR}/num_leaves"`
1094                         num_leaves=`wc -l < ${DBDIR}/grep.leaf_ports.pattern | tr -d ' '`
1095                         num_leaves_new=`echo $(($num_leaves-$num_leaves_prev)) | tr -d ' '`
1096                         if [ $num_leaves_new -eq 0 ]
1097                         then
1098                                 message_echo "  No more leaf port is found."
1099                                 message_echo "  $num_leaves leaf port(s) is/are found in total."
1100                                 break
1101                         fi
1102                         {
1103                                 grep -E -v -f "${DBDIR}/grep.leaf_ports.pattern" \
1104                                         "${DBDIR}/stage.loop_list/leaf_ports_secondary_candidates" || :
1105                                 cat "${DBDIR}/leaf_ports_secondary_candidates.new_requirements" || :
1106                         } | grep -v -E -f "${DBDIR}/conf/HOLD_PORTS.grep_pattern" | sort -u \
1107                                 > ${DBDIR}/stage.loop_list/leaf_ports_secondary_candidates.tmp || :
1108                         program_reset_loop_for_stage INSPECT_REQUIREMENTS_OF_LEAF_PORTS
1109                         mv "${DBDIR}/stage.loop_list/leaf_ports_secondary_candidates.tmp" \
1110                                 "${DBDIR}/stage.loop_list/leaf_ports_secondary_candidates"
1111                         cp /dev/null "${DBDIR}/leaf_ports_secondary_candidates.new_requirements"
1112                         echo "$num_leaves" > ${DBDIR}/num_leaves
1113                         num_inspect=`wc -l < ${DBDIR}/stage.loop_list/leaf_ports_secondary_candidates | tr -d ' '`
1114                         message_echo "  $num_leaves_new leaf port(s) is/are newly found; continue for $num_inspect candidate(s)."
1115                 done
1116                 grep -E -f "${DBDIR}/grep.leaf_ports.pattern" "${DBDIR}/inspected_ports" | sort -u > ${DBDIR}/leaf_ports || :
1117                 message_echo
1118         }
1119         program_exec_and_record_completion INSPECT_REQUIREMENTS_OF_LEAF_PORTS
1120 fi
1121
1122 # Order the ports considering dependencies
1123 PROGRAM_DEPENDS='CONVERT_REQUIREMENTS_LIST'
1124 _program_exec_and_record_completion__operation ()
1125 {
1126         message_section_title "Ordering dependencies"
1127         if ! database_build_order_ports_considering_dependencies
1128         then
1129                 message_echo "ERROR: Unsatisfied dependencies are remained:" >&2
1130                 message_cat "${DBDIR}/unsatisfied.list"
1131                 message_echo "*** Aborted by ${APPNAME}"
1132                 message_echo "The ports tree seems broken. You might have caught an incomplete version."
1133                 message_echo "You are encouraged to update the ports tree by portsnap(8)."
1134                 message_echo "Then execute"
1135                 message_echo " ${APPNAME} clean"
1136                 message_echo "before restart."
1137                 temp_terminate_process () { :; }
1138                 exit 1
1139         fi
1140         message_echo
1141 }
1142 program_exec_and_record_completion ORDER_ALL_DEPENDENCIES
1143
1144 # Selection of removing leaf ports
1145 PROGRAM_DEPENDS='INSPECT_REQUIREMENTS_OF_LEAF_PORTS'
1146 _program_exec_and_record_completion__operation ()
1147 {
1148         message_section_title "Selection of removing leaf ports"
1149         deinstall_select_leaf_ports_to_delete
1150         message_echo
1151 }
1152 program_exec_and_record_completion SELECT_LEAF_PORTS
1153
1154 # Selection of removing obsolete ports
1155 PROGRAM_DEPENDS='INSPECT_ALL_DEPENDENCIES PARSE_CONF'
1156 _program_exec_and_record_completion__operation ()
1157 {
1158         message_section_title "Selection of removing obsolete ports"
1159         deinstall_select_obsolete_ports_to_delete
1160         message_echo
1161 }
1162 program_exec_and_record_completion SELECT_OBSOLETE_PORTS
1163
1164 # Collection of leaf ports to delete
1165 if [ ! -e "${DBDIR}/inspected_ports_only_partially" ]
1166 then
1167         PROGRAM_DEPENDS='SELECT_LEAF_PORTS'
1168         _program_exec_and_record_completion__operation ()
1169         {
1170                 local src src_unselected reqptn_file src_with_initial_origins
1171                 message_section_title "Collecting leaf ports to delete"
1172                 src=${DBDIR}/leaf_ports
1173                 src_unselected=${DBDIR}/leaf_ports_to_delete.unselected
1174                 src_with_initial_origins=${DBDIR}/leaf_ports.with_ini
1175                 reqptn_file=${DBDIR}/leaf_ports.requirements_of_unselected.grep_pattern
1176                 cat "$src_unselected" 2> /dev/null | while read origin
1177                 do
1178                         cat "${DBDIR}/requires/$origin/requirements.all.full" || :
1179                 done | sort -u | str_escape_regexp_filter \
1180                         | sed 's/^/^/;s/$/$/' > $reqptn_file
1181                 database_query_add_initial_origins < $src > $src_with_initial_origins
1182                 message_echo
1183         }
1184         program_exec_and_record_completion COLLECT_LEAF_PORTS_TO_DELETE
1185 fi
1186
1187 # Collection of obsolete ports to delete
1188 PROGRAM_DEPENDS='SELECT_OBSOLETE_PORTS'
1189 _program_exec_and_record_completion__operation ()
1190 {
1191         local src src_selected src_unselected dst_selected reqptn_file
1192         message_section_title "Collecting obsolete ports to delete"
1193         src=${DBDIR}/obsolete_ports.can_be_deleted
1194         src_selected=${DBDIR}/obsolete_ports_to_delete.selected
1195         src_unselected=${DBDIR}/obsolete_ports_to_delete.unselected
1196         dst_selected=${DBDIR}/obsolete_ports_to_delete
1197         reqptn_file=${DBDIR}/obsolete_ports.requirements_of_unselected.grep_pattern
1198         cat "$src_unselected" 2> /dev/null | while read origin
1199         do
1200                 cat "${DBDIR}/initial/$origin/requirements.run.full" || :
1201                 cat "${DBDIR}/obsolete/$origin/requirements.run.full" || :
1202         done | sort -u | str_escape_regexp_filter \
1203                 | sed 's/^/^/;s/$/$/' > $reqptn_file
1204         grep -v -E -f "$reqptn_file" "$src_selected" > $dst_selected 2> /dev/null || :
1205         message_echo
1206 }
1207 program_exec_and_record_completion COLLECT_OBSOLETE_PORTS_TO_DELETE
1208
1209 # Set up the list of ports to reinstall
1210 PROGRAM_DEPENDS='ORDER_ALL_DEPENDENCIES'
1211 _program_exec_and_record_completion__operation ()
1212 {
1213         message_section_title "Setting up the list of ports to reinstall"
1214         cp -p "${DBDIR}/reinst_order.list" "${DBDIR}/stage.loop_list/reinst_todo"
1215         message_echo
1216 }
1217 program_exec_and_record_completion SETUP_REINST_TODO
1218
1219 # Composition of a list for deinstallation of obsolete and leaf packages
1220 PROGRAM_DEPENDS='COLLECT_LEAF_PORTS_TO_DELETE COLLECT_OBSOLETE_PORTS_TO_DELETE'
1221 _program_exec_and_record_completion__operation ()
1222 {
1223         local reqptn_leaf reqptn_obs leaf_selected leaf_selected_src obs_selected obs_selected_src grepptn preserved
1224         message_section_title "Composing a list for deinstallation of obsolete and leaf packages"
1225         reqptn_leaf=${DBDIR}/leaf_ports.requirements_of_unselected.grep_pattern
1226         reqptn_obs=${DBDIR}/obsolete_ports.requirements_of_unselected.grep_pattern
1227         leaf_selected_src=${DBDIR}/leaf_ports_to_delete.selected
1228         leaf_selected=${DBDIR}/leaf_ports_to_delete
1229         obs_selected_src=${DBDIR}/obsolete_ports_to_delete.selected
1230         obs_selected=${DBDIR}/obsolete_ports_to_delete
1231         grepptn=${DBDIR}/ports_to_delete.grep_pattern
1232         grepptn_col1=${DBDIR}/ports_to_delete.grep_pattern_col1
1233         preserved=${TMPDIR}/LIST_DEINST_PKGS::preserved
1234         if [ ! -e "${DBDIR}/inspected_ports_only_partially" ]
1235         then
1236                 cat "$reqptn_leaf" "$reqptn_obs" 2> /dev/null | sort -u > $grepptn
1237                 grep -v -E -f "$grepptn" "$leaf_selected_src" 2> /dev/null \
1238                         | database_query_add_initial_origins > $leaf_selected || :
1239                 cat "$obs_selected" "$leaf_selected" 2> /dev/null || :
1240         else
1241                 rm -f "$leaf_selected"
1242                 cat "$obs_selected" 2> /dev/null
1243         fi | sort -u > ${DBDIR}/stage.loop_list/ports_to_delete
1244         str_escape_regexp_filter < ${DBDIR}/stage.loop_list/ports_to_delete \
1245                 | sed 's/^/^/;s/$/$/' > $grepptn
1246         str_escape_regexp_filter < ${DBDIR}/stage.loop_list/ports_to_delete \
1247                 | sed 's/^/^/;s/$/[[:space:]]/' > $grepptn_col1
1248         cat "${DBDIR}/leaf_ports.with_ini" "${DBDIR}/obsolete_ports" 2> /dev/null \
1249                 | grep -E -v -f "$grepptn" > ${DBDIR}/stage.loop_list/ports_to_restore || :
1250         if [ $opt_batch_mode = no ]
1251         then
1252                 if [ ! -e "${DBDIR}/inspected_ports_only_partially" ] && \
1253                         grep -v -E -f "$grepptn" "$leaf_selected_src" > $preserved 2> /dev/null
1254                 then
1255                         message_echo "INFO: Following leaf ports are preserved because required by other preserved leaf/obsolete ports."
1256                         message_echo "----------------"
1257                         while read origin
1258                         do
1259                                 pkgtag=`cat "${DBDIR}/required/$origin/pkgtag" 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                 if grep -v -E -f "$grepptn" "$obs_selected_src" > $preserved 2> /dev/null
1270                 then
1271                         message_echo "INFO: Following obsolete ports are preserved because required by other obsolete ports."
1272                         message_echo "----------------"
1273                         while read origin
1274                         do
1275                                 pkgtag=`cat "${DBDIR}/initial/$origin/installed_version" 2> /dev/null` || :
1276                                 if [ -n "$pkgtag" ]
1277                                 then
1278                                         echo "$origin" "($pkgtag)"
1279                                 else
1280                                         echo "$origin"
1281                                 fi
1282                         done < $preserved
1283                         message_echo "----------------"
1284                 fi
1285         fi
1286         message_echo
1287 }
1288 program_exec_and_record_completion LIST_DEINST_PKGS
1289
1290 # Collect entire distfiles list
1291 if [ $opt_inspect_entire_distinfo = yes ]
1292 then
1293         PROGRAM_DEPENDS=''
1294         _program_exec_and_record_completion__operation ()
1295         {
1296                 message_section_title "Collecting entire distfiles list"
1297                 find "${PORTSDIR}" -depth 3 -name distinfo -exec cat {} \; \
1298                         | grep '^SHA256 ' | sed -E 's/^SHA256 \(([^)]*)\).*/\1/' \
1299                         | sort -u > ${DBDIR}/distfiles.entire.tmp
1300                 mv "${DBDIR}/distfiles.entire.tmp" "${DBDIR}/distfiles.entire"
1301                 message_echo
1302         }
1303         program_exec_and_record_completion COLLECT_ALL_DISTFILES_LIST
1304 fi
1305
1306 # Inspection of all required distfiles
1307 PROGRAM_DEPENDS='INSPECT_ALL_DEPENDENCIES COLLECT_ALL_DISTFILES_LIST'
1308 _program_exec_and_record_completion__operation ()
1309 {
1310         message_section_title "Summarizing distfiles list"
1311         cat "${DBDIR}/distfiles.entire" "${DBDIR}/distfiles.inspected" 2> /dev/null \
1312                 | sort -u | str_escape_regexp_filter \
1313                 | sed 's|^|^\\.\\/|; s|$|$|' > ${DBDIR}/distfiles.grep.pattern || :
1314         message_echo
1315 }
1316 program_exec_and_record_completion DISTFILES_LIST
1317
1318 # Clean up of reinstallation status for preparation
1319 PROGRAM_DEPENDS='REDO_INIT INSPECT_ALL_DEPENDENCIES'
1320 _program_exec_and_record_completion__operation ()
1321 {
1322         message_section_title "Cleaning up of reinstallation status for preparation"
1323         rm -rf "${DBDIR}/status.ports"
1324         message_echo
1325 }
1326 program_exec_and_record_completion CLEANUP_REINST_STATUS
1327
1328 # Completion of building the temporary database
1329 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'
1330 _program_exec_and_record_completion__operation ()
1331 {
1332         message_section_title "The temporary database is completely built up"
1333         message_echo
1334 }
1335 program_exec_and_record_completion PREPARATION
1336
1337
1338 # ==================================================
1339 # ====================== MAIN ======================
1340 # ==================================================
1341
1342 # Execute command operations which must be done before actual (re/de)installation processes
1343 command_exec_before_actual_re_de_installation "$@"
1344
1345 # Set termination messages
1346 temp_terminate_process ()
1347 {
1348         temp_terminate_process_common
1349 }
1350
1351 # Reinstallation of remained ports
1352 PROGRAM_DEPENDS='PREPARATION'
1353 _program_exec_restartable_loop_operation__routine ()
1354 {
1355         reinstall_exec "$@"
1356 }
1357 _program_exec_and_record_completion__operation ()
1358 {
1359         local _MSG_CURRENT_STAGE_general
1360         _MSG_CURRENT_STAGE_general="reinstallation"
1361         temp_set_msg_current_stage "${_MSG_CURRENT_STAGE_general}"
1362         message_section_title "Reinstallation"
1363         program_exec_restartable_loop_operation reinst_todo
1364         reinstall_restore_conflicts
1365         temp_set_msg_current_stage
1366         message_echo
1367 }
1368 program_exec_and_record_completion REINSTALLATION
1369
1370 # Restoration of obsolete and leaf packages which have been deinstalled but unselected from the deletion list again 
1371 PROGRAM_DEPENDS='REDO_INIT LIST_DEINST_PKGS'
1372 _program_exec_restartable_loop_operation__routine ()
1373 {
1374         deinstall_restore "$@"
1375 }
1376 _program_exec_and_record_completion__operation ()
1377 {
1378         local _MSG_CURRENT_STAGE_general
1379         _MSG_CURRENT_STAGE_general="restoration of unselected obsolete/leaf packages"
1380         temp_set_msg_current_stage "${_MSG_CURRENT_STAGE_general}"
1381         message_section_title "Restoration of unselected obsolete/leaf packages"
1382         program_exec_restartable_loop_operation ports_to_restore
1383         temp_set_msg_current_stage
1384         message_echo
1385 }
1386 program_exec_and_record_completion RESTORE_ONCE_DEINST_PKGS
1387
1388 # Deinstallation of unused obsolete and leaf packages
1389 PROGRAM_DEPENDS='REDO_INIT LIST_DEINST_PKGS'
1390 _program_exec_restartable_loop_operation__routine ()
1391 {
1392         deinstall_exec "$@"
1393 }
1394 _program_exec_and_record_completion__operation ()
1395 {
1396         local _MSG_CURRENT_STAGE_general
1397         _MSG_CURRENT_STAGE_general="deinstallation of obsolete/leaf packages"
1398         temp_set_msg_current_stage "${_MSG_CURRENT_STAGE_general}"
1399         message_section_title "Deinstallation of unused obsolete/leaf packages"
1400         program_exec_restartable_loop_operation ports_to_delete
1401         temp_set_msg_current_stage
1402         message_echo
1403 }
1404 program_exec_and_record_completion DEINST_UNUSED_PKGS
1405
1406 # Clean up obsolete or unused distfiles
1407 if [ $opt_only_target_scope = no -a $opt_keep_distfiles = no ]
1408 then
1409         PROGRAM_DEPENDS='REINSTALLATION DISTFILES_LIST'
1410         _program_exec_and_record_completion__operation ()
1411         {
1412                 local tmp_distfiles_exists
1413                 message_section_title "Cleaning up obsolete or unused distfiles"
1414                 tmp_distfiles_exists=${TMPDIR}/CLEANUP_OBSLETE_DISTFILES::distfiles_exists
1415                 [ $opt_dry_run = yes ] && message_echo "INFO: The operations are not actually carried out."
1416                 ( set -e; cd "${DISTDIR}" && find . -type f ) \
1417                         | sed 's|^\./||' | sort -u > $tmp_distfiles_exists
1418                 fileedit_manipulate_old_lines "$tmp_distfiles_exists" "${DBDIR}/distfiles.entire" \
1419                         | while read distfile
1420                 do
1421                         if [ $opt_batch_mode = no ]
1422                         then
1423                                 echo "  $distfile"
1424                         fi
1425                         [ $opt_dry_run = yes ] && continue
1426                         rm -f "${DISTDIR}/$distfile"
1427                 done
1428                 message_echo
1429         }
1430         program_exec_and_record_completion CLEANUP_OBSLETE_DISTFILES
1431 fi
1432
1433 # Rebuild of package database
1434 PROGRAM_DEPENDS='REINSTALLATION RESTORE_ONCE_DEINST_PKGS DEINST_UNUSED_PKGS'
1435 _program_exec_and_record_completion__operation ()
1436 {
1437         which -s pkgdb || return 0
1438         message_section_title "Rebuilding package database for portupgrade"
1439         pkgdb -fu
1440         message_echo
1441 }
1442 program_exec_and_record_completion REBUILD_PKGDB
1443
1444
1445 # ==================================================
1446 # ================ ENDING MESSAGES =================
1447 # ==================================================
1448
1449 # Notice of failures
1450 exists_unresolved_ports=
1451 message_summary_dependents_of_failed_reinstallation failure || exists_unresolved_ports=y
1452 message_summary_dependents_of_failed_reinstallation redo || exists_unresolved_ports=y
1453 message_summary_dependents_of_failed_reinstallation conflict || exists_unresolved_ports=y
1454 [ -n "$exists_unresolved_ports" ] && message_summary_advice_on_manual_solution
1455
1456 # End
1457 temp_terminate_process () { :; }
1458
1459 if [ -z "$exists_unresolved_ports" ]
1460 then
1461         message_section_title "COMPLETELY DONE"
1462         message_echo "- E N D -"
1463 else
1464         message_warn_no_achieved_progress || :
1465         message_section_title "Done with some unresolved problems"
1466         message_echo "- To be continued -"
1467 fi