OSDN Git Service

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