OSDN Git Service

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