OSDN Git Service

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