OSDN Git Service

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