OSDN Git Service

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