OSDN Git Service

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