OSDN Git Service

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