OSDN Git Service

Version 3.3.2+toward_4.0.0_20180629133501
authorMamoru Sakaue / MwGhennndo <glmwghennndo@users.sourceforge.jp>
Fri, 29 Jun 2018 05:43:50 +0000 (13:43 +0800)
committerMamoru Sakaue / MwGhennndo <glmwghennndo@users.sourceforge.jp>
Fri, 29 Jun 2018 05:43:50 +0000 (13:43 +0800)
The library structures are largely changed for implementation of new executable scripts.

[NEW] Flavor is supported. Related to this feature, representations of port origins without flavor is recognized to exactly match the unflavored ones.

[NEW] Option -F is added.

[NEW] packupgrade command is added.

[NEW] reset keepstatus command is added.

[NEW] freeze and show freeze commands are added. FREEZE section is added to ${LOCALBASE}/etc/portsreinstall.conf.

[NEW] show conflict_files command is added.

[NEW] CONFLICT section is added to ${LOCALBASE}/etc/portsreinstall.conf.

[NEW] Utilities of portsreinstall-upgrade(8) and portsreinstall-chroot(8) are added.

[NEW] Change of port options made outside of portsreinstall(8) is automatically detected.

[IMPROVED] The (re)installation process is changed to be repeated until all-automatically resolvable problems are resolved. Thus there is no more need to simply repeat redo command to complete the automatic solution.

[IMPROVED] The way of detecting the packages system is changed to check both WITH_PKG and WITH_PKGNG in accordance with the specification change of the ports tree. The descriptions about the packages system is updated as well.

[IMPROVED] reset command is improved to reset the database cleaner and preserve manually set taboo/freeze/need/noneed lists.

[IMPROVED] reconf command is changed to be available any time.

[IMPROVED] Inspection of merged ports is improved to make the deinstallation of old packages effective.

[BUG FIX] pkgsanity command had lost its ability to detect missing files because of the specification change of pkg(8).

[BUG FIX] Command line arguments could have interpreted "add" keyword as a glog matching math/add.

[BUG FIX] Option -k did not work properly with option -g.

 Changes to be committed:
modified:   COPYRIGHT
modified:   INSTALL
modified:   Makefile
modified:   README
modified:   bin/portsreinstall
new file:   bin/portsreinstall-chroot
modified:   etc/portsreinstall.conf
new file:   lib/chroot-mount/libcommand.sh
new file:   lib/chroot-mount/libconf.sh
new file:   lib/chroot-mount/libdatabase_maintain.sh
new file:   lib/chroot-mount/libmain.sh
new file:   lib/chroot-mount/libmessage.sh
new file:   lib/chroot-mount/liboptions.sh
new file:   lib/chroot-mount/libtemp.sh
new file:   lib/chroot-mount/libusage.sh
new file:   lib/chroot/libcommand.sh
new file:   lib/chroot/libcommand_do.sh
new file:   lib/chroot/libdatabase_maintain.sh
new file:   lib/chroot/libfs.sh
new file:   lib/chroot/libmain.sh
new file:   lib/chroot/libmessage.sh
new file:   lib/chroot/liboptions.sh
new file:   lib/chroot/libusage.sh
modified:   lib/libcommand.sh
new file:   lib/libcommand_do.sh
new file:   lib/libcommand_flexconf.sh
new file:   lib/libcommand_forget.sh
new file:   lib/libcommand_pkgs.sh
new file:   lib/libcommand_show.sh
modified:   lib/libconf.sh
modified:   lib/libdatabase_build.sh
new file:   lib/libdatabase_maintain.sh
modified:   lib/libdatabase_query.sh
modified:   lib/libdatabase_record.sh
modified:   lib/libdeinstall.sh
        modified:   lib/libfileedit.sh
new file:   lib/libmain.sh
modified:   lib/libmessage.sh
modified:   lib/libmisc.sh
modified:   lib/liboptions.sh
modified:   lib/libpkgsys.sh
modified:   lib/libprogram.sh
modified:   lib/libreinstall.sh
modified:   lib/libstr.sh
modified:   lib/libtemp.sh
modified:   lib/libusage.sh
new file:   lib/main/libcommand.sh
new file:   lib/main/liboptions.sh
new file:   lib/main/libtemp.sh
copied:     lib/libusage.sh -> lib/main/libusage.sh
new file:   lib/upgrade/libcommand.sh
new file:   lib/upgrade/libcommand_do.sh
new file:   lib/upgrade/libmain.sh
new file:   lib/upgrade/libmessage.sh
new file:   lib/upgrade/liboptions.sh
new file:   lib/upgrade/libusage.sh
new file:   libexec/order_dependencies.awk
new file:   man/portsreinstall-chroot-mount.8
new file:   man/portsreinstall-chroot.8
new file:   man/portsreinstall-upgrade.8
modified:   man/portsreinstall.8
new file:   share/bin/portsreinstall-chroot-mount
new file:   share/bin/portsreinstall-upgrade

63 files changed:
COPYRIGHT
INSTALL
Makefile
README
bin/portsreinstall
bin/portsreinstall-chroot [new file with mode: 0755]
etc/portsreinstall.conf
lib/chroot-mount/libcommand.sh [new file with mode: 0644]
lib/chroot-mount/libconf.sh [new file with mode: 0644]
lib/chroot-mount/libdatabase_maintain.sh [new file with mode: 0644]
lib/chroot-mount/libmain.sh [new file with mode: 0644]
lib/chroot-mount/libmessage.sh [new file with mode: 0644]
lib/chroot-mount/liboptions.sh [new file with mode: 0644]
lib/chroot-mount/libtemp.sh [new file with mode: 0644]
lib/chroot-mount/libusage.sh [new file with mode: 0644]
lib/chroot/libcommand.sh [new file with mode: 0644]
lib/chroot/libcommand_do.sh [new file with mode: 0644]
lib/chroot/libdatabase_maintain.sh [new file with mode: 0644]
lib/chroot/libfs.sh [new file with mode: 0644]
lib/chroot/libmain.sh [new file with mode: 0644]
lib/chroot/libmessage.sh [new file with mode: 0644]
lib/chroot/liboptions.sh [new file with mode: 0644]
lib/chroot/libusage.sh [new file with mode: 0644]
lib/libcommand.sh
lib/libcommand_do.sh [new file with mode: 0644]
lib/libcommand_flexconf.sh [new file with mode: 0644]
lib/libcommand_forget.sh [new file with mode: 0644]
lib/libcommand_pkgs.sh [new file with mode: 0644]
lib/libcommand_show.sh [new file with mode: 0644]
lib/libconf.sh
lib/libdatabase_build.sh
lib/libdatabase_maintain.sh [new file with mode: 0644]
lib/libdatabase_query.sh
lib/libdatabase_record.sh
lib/libdeinstall.sh
lib/libfileedit.sh
lib/libmain.sh [new file with mode: 0644]
lib/libmessage.sh
lib/libmisc.sh
lib/liboptions.sh
lib/libpkgsys.sh
lib/libprogram.sh
lib/libreinstall.sh
lib/libstr.sh
lib/libtemp.sh
lib/libusage.sh
lib/main/libcommand.sh [new file with mode: 0644]
lib/main/liboptions.sh [new file with mode: 0644]
lib/main/libtemp.sh [new file with mode: 0644]
lib/main/libusage.sh [new file with mode: 0644]
lib/upgrade/libcommand.sh [new file with mode: 0644]
lib/upgrade/libcommand_do.sh [new file with mode: 0644]
lib/upgrade/libmain.sh [new file with mode: 0644]
lib/upgrade/libmessage.sh [new file with mode: 0644]
lib/upgrade/liboptions.sh [new file with mode: 0644]
lib/upgrade/libusage.sh [new file with mode: 0644]
libexec/order_dependencies.awk [new file with mode: 0755]
man/portsreinstall-chroot-mount.8 [new file with mode: 0644]
man/portsreinstall-chroot.8 [new file with mode: 0644]
man/portsreinstall-upgrade.8 [new file with mode: 0644]
man/portsreinstall.8
share/bin/portsreinstall-chroot-mount [new file with mode: 0755]
share/bin/portsreinstall-upgrade [new file with mode: 0644]

index 33a4862..088e55f 100644 (file)
--- a/COPYRIGHT
+++ b/COPYRIGHT
@@ -1,7 +1,7 @@
 This software is distributed under the following terms of which the
 compilation corresponds to the 2-Clause BSD License:
 
-Copyright 2010-2017 Mamoru Sakaue, MwGhennndo. All rights reserved.
+Copyright 2010-2018 Mamoru Sakaue, MwGhennndo. All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions
diff --git a/INSTALL b/INSTALL
index 0bf199d..785dba4 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -1,18 +1,17 @@
 # ==============================================================================
 # portsreinstall installation guide
-# Copyright (C) 2010-2017 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# Copyright (C) 2010-2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
 # ==============================================================================
 
  For managements within the port/packages system,
 the installation is available by
         make -C /usr/ports/ports-mgmt/portsreinstall install clean
+or
+        pkg add ports-mgmt/portsreinstall
 and the deinstallation is by
         make -C /usr/ports/ports-mgmt/portsreinstall deinstall
 or
-        pkg_delete portsreinstall-\*
-for the legacy packages and
-        pkg delete portsreinstall-\*
-for the new generation packages (pkgng).
+        pkg delete ports-mgmt/portsreinstall
 
  The following part of this file explains how to install/deinstall this software
 outside of the port/packages system.
@@ -26,7 +25,7 @@ the files installed outside of the port/packages system.
  FreeBSD 7.x-RELEASE and later are intended systems to support.
  The first version of this software was developed on FreeBSD 7.3-RELEASE and
 8.1-RELEASE. The latest version was developed on FreeBSD 8.3-RELEASE. Both the
-legacy packages system and the new generation packages (pkgng) system are
+legacy packages system and the modern packages system (formerly called new generation packages ,pkgng) are
 supported.
 
 
index c4f0a04..8e43328 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 # ==============================================================================
 # portsreinstall installation makefile
-# Copyright (C) 2010-2017 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# Copyright (C) 2010-2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
 # ==============================================================================
 
 PROGNAME=      portsreinstall
@@ -14,33 +14,97 @@ RM= rm -f
 RMDIR= rm -fr
 GZIP=  gzip -f
 
-LIBS=  lib/liboptions.sh \
-       lib/libtemp.sh \
-       lib/libstr.sh \
-       lib/libusage.sh \
-       lib/libmessage.sh \
-       lib/libpkgsys.sh \
-       lib/libmisc.sh \
-       lib/libfileedit.sh \
+BINS=\
+       bin/$(PROGNAME) \
+       bin/$(PROGNAME)-chroot
+LIBS=\
+       lib/libcommand.sh \
+       lib/libcommand_do.sh \
+       lib/libcommand_flexconf.sh \
+       lib/libcommand_forget.sh \
+       lib/libcommand_pkgs.sh \
+       lib/libcommand_show.sh \
        lib/libconf.sh \
        lib/libdatabase_build.sh \
+       lib/libdatabase_maintain.sh \
        lib/libdatabase_query.sh \
        lib/libdatabase_record.sh \
-       lib/libcommand.sh \
+       lib/libdeinstall.sh \
+       lib/libfileedit.sh \
+       lib/libmain.sh \
+       lib/libmessage.sh \
+       lib/libmisc.sh \
+       lib/liboptions.sh \
+       lib/libpkgsys.sh \
        lib/libprogram.sh \
        lib/libreinstall.sh \
-       lib/libdeinstall.sh
+       lib/libstr.sh \
+       lib/libtemp.sh \
+       lib/libusage.sh
+LIBS_MAIN=\
+       lib/main/libcommand.sh \
+       lib/main/liboptions.sh \
+       lib/main/libtemp.sh \
+       lib/main/libusage.sh
+LIBS_CHROOT=\
+       lib/chroot/libcommand.sh \
+       lib/chroot/libcommand_do.sh \
+       lib/chroot/libdatabase_maintain.sh \
+       lib/chroot/libfs.sh \
+       lib/chroot/libmain.sh \
+       lib/chroot/libmessage.sh \
+       lib/chroot/liboptions.sh \
+       lib/chroot/libusage.sh
+LIBS_CHROOT_MOUNT=\
+       lib/chroot-mount/libcommand.sh \
+       lib/chroot-mount/libconf.sh \
+       lib/chroot-mount/libdatabase_maintain.sh \
+       lib/chroot-mount/libmain.sh \
+       lib/chroot-mount/libmessage.sh \
+       lib/chroot-mount/liboptions.sh \
+       lib/chroot-mount/libtemp.sh \
+       lib/chroot-mount/libusage.sh
+LIBS_UPGRADE=\
+       lib/upgrade/libcommand.sh \
+       lib/upgrade/libcommand_do.sh \
+       lib/upgrade/libmain.sh \
+       lib/upgrade/libmessage.sh \
+       lib/upgrade/liboptions.sh \
+       lib/upgrade/libusage.sh
+LIBEXECS=\
+       libexec/order_dependencies.awk
+PROGNAMES_DISPATCH=\
+       share/bin/$(PROGNAME)-upgrade \
+       share/bin/$(PROGNAME)-chroot-mount
 
 all:
 
 install:
        $(INSTALL_DIR) $(PREFIX)/bin
-       $(INSTALL_SCRIPT) bin/$(PROGNAME) $(PREFIX)/bin
+       $(INSTALL_SCRIPT) $(BINS) $(PREFIX)/bin
        $(INSTALL_DIR) $(PREFIX)/lib/$(PROGNAME)
        $(INSTALL_NOEXEC) $(LIBS) $(PREFIX)/lib/$(PROGNAME)
+       $(INSTALL_DIR) $(PREFIX)/lib/$(PROGNAME)/main
+       $(INSTALL_NOEXEC) $(LIBS_MAIN) $(PREFIX)/lib/$(PROGNAME)/main
+       $(INSTALL_DIR) $(PREFIX)/lib/$(PROGNAME)/chroot
+       $(INSTALL_NOEXEC) $(LIBS_CHROOT) $(PREFIX)/lib/$(PROGNAME)/chroot
+       $(INSTALL_DIR) $(PREFIX)/lib/$(PROGNAME)/chroot-mount
+       $(INSTALL_NOEXEC) $(LIBS_CHROOT_MOUNT) $(PREFIX)/lib/$(PROGNAME)/chroot-mount
+       $(INSTALL_DIR) $(PREFIX)/lib/$(PROGNAME)/upgrade
+       $(INSTALL_NOEXEC) $(LIBS_UPGRADE) $(PREFIX)/lib/$(PROGNAME)/upgrade
+       $(INSTALL_DIR) $(PREFIX)/libexec/$(PROGNAME)
+       $(INSTALL_SCRIPT) $(LIBEXECS) $(PREFIX)/libexec/$(PROGNAME)
        $(INSTALL_DIR) $(PREFIX)/man/man8
        $(INSTALL_NOEXEC) man/$(PROGNAME).8 $(PREFIX)/man/man8
        $(GZIP) ${PREFIX}/man/man8/$(PROGNAME).8
+       $(INSTALL_NOEXEC) man/$(PROGNAME)-chroot.8 $(PREFIX)/man/man8
+       $(GZIP) ${PREFIX}/man/man8/$(PROGNAME)-chroot.8
+       $(INSTALL_NOEXEC) man/$(PROGNAME)-chroot-mount.8 $(PREFIX)/man/man8
+       $(GZIP) ${PREFIX}/man/man8/$(PROGNAME)-chroot-mount.8
+       $(INSTALL_NOEXEC) man/$(PROGNAME)-upgrade.8 $(PREFIX)/man/man8
+       $(GZIP) ${PREFIX}/man/man8/$(PROGNAME)-upgrade.8
+       $(INSTALL_DIR) $(PREFIX)/share/$(PROGNAME)/bin
+       $(INSTALL_SCRIPT) $(PROGNAMES_DISPATCH) $(PREFIX)/share/$(PROGNAME)/bin
        $(INSTALL_DIR) $(PREFIX)/etc
        $(INSTALL_CONF) etc/$(PROGNAME).conf $(PREFIX)/etc/$(PROGNAME).conf.sample
        if [ ! -e $(PREFIX)/etc/$(PROGNAME).conf ]; then $(INSTALL_CONF) etc/$(PROGNAME).conf $(PREFIX)/etc; fi
@@ -50,6 +114,8 @@ clean:
 deinstall:
        $(RM) ${PREFIX}/bin/$(PROGNAME)
        $(RMDIR) $(PREFIX)/lib/$(PROGNAME)
+       $(RMDIR) $(PREFIX)/libexec/$(PROGNAME)
+       $(RMDIR) $(PREFIX)/share/$(PROGNAME)
        $(RM) ${PREFIX}/man/man8/$(PROGNAME).8.gz
-       if diff $(PREFIX)/etc/$(PROGNAME).conf $(PREFIX)/etc/$(PROGNAME).conf.sample > /dev/null 2> /dev/null; then $(RM) $(PREFIX)/etc/$(PROGNAME).conf; fi
+       if diff -q $(PREFIX)/etc/$(PROGNAME).conf $(PREFIX)/etc/$(PROGNAME).conf.sample > /dev/null 2> /dev/null; then $(RM) $(PREFIX)/etc/$(PROGNAME).conf; fi
        $(RM) ${PREFIX}/etc/$(PROGNAME).conf.sample
diff --git a/README b/README
index 221325d..34d288c 100644 (file)
--- a/README
+++ b/README
@@ -1,7 +1,7 @@
 ================================================================================
  portsreinstall - ports upgrading utility for massive forced reinstallation
-  Version 3.3.3, May 22, 2017
- Copyright (C) 2010-2017 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+  Version 4.0.0, June 22, 2018
+ Copyright (C) 2010-2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
 ================================================================================
 
  This software is a ports management tool for FreeBSD designed to be suitable
@@ -21,14 +21,15 @@ be preserved until you complete or give up the reinstallation work. The database
 can be cleaned by executing "portsreinstall clean".
 
  This software consists of the following files:
-        README          : This file
-        COPYRIGHT       : Copyright and license terms
-        INSTALL         : Installation guide
-        Makefile        : Makefile usable by make(1)
-        etc/            : Run-time configuration files
-        lib/            : Run-time libraries
-        bin/            : Run-time executables
-        man/            : On-line manual pages
+        README                 : This file
+        COPYRIGHT              : Copyright and license terms
+        INSTALL                        : Installation guide
+        Makefile                       : Makefile usable by make(1)
+        etc/                           : Run-time configuration files
+        lib/                           : Run-time libraries
+        bin/                           : Run-time executables
+        man/                   : On-line manual pages
+        share/                 : Files used for other purposes
 
  The all files in this package are distributed under the 2-Clause BSD License as
 described in COPYRIGHT.
index 7c30a4f..bbcb57a 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh -e
 # ==================================================================================
 # portsreinstall main script
-# Copyright (C) 2010-2017 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# Copyright (C) 2010-2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
 # This software is distributed under the 2-Clause BSD License.
 # ==================================================================================
 
 # ==================================================
 
 # ============ Set up of environment =============
+PROGRAM=portsreinstall
 APPNAME=`basename "$0"`
 
-MYVERSION=3.3.3
-COMPATIBLE_VERSIONS='^(3\.[1-3]\.[0-9]+)$'
-# Template for development versions
-MYVERSION=3.3.2+toward_3.3.3_20170522123653
-COMPATIBLE_VERSIONS='^(3\.[1-3]\.[0-9]+\+toward_3\.[1-3]\.[0-9]+_[0-9]+|3\.[1-3]\.[0-9]+)$'
-MYPREFIX=`dirname "\`dirname \"$0\"\`" | sed 's|/bin$||'`
-MYPREFIX=${MYPREFIX:-/usr/local}
-LIBDIR=${MYPREFIX}/lib/${APPNAME}
+MYPREFIX=`realpath "\`dirname \"$0\"\`"/..`
+LIBDIR=${MYPREFIX}/lib/${PROGRAM}
+LIBEXECDIR=${MYPREFIX}/libexec/${PROGRAM}
+SHAREDIR=${MYPREFIX}/share/${PROGRAM}
+ETCDIR=${MYPREFIX}/etc
 
-. ${LIBDIR}/libtemp.sh
-. ${LIBDIR}/libstr.sh
-. ${LIBDIR}/liboptions.sh
-. ${LIBDIR}/libusage.sh
-. ${LIBDIR}/libmessage.sh
-. ${LIBDIR}/libpkgsys.sh
-. ${LIBDIR}/libmisc.sh
-. ${LIBDIR}/libfileedit.sh
+. ${LIBDIR}/libcommand.sh
+. ${LIBDIR}/libcommand_do.sh
+. ${LIBDIR}/libcommand_flexconf.sh
+. ${LIBDIR}/libcommand_forget.sh
+. ${LIBDIR}/libcommand_pkgs.sh
+. ${LIBDIR}/libcommand_show.sh
 . ${LIBDIR}/libconf.sh
 . ${LIBDIR}/libdatabase_build.sh
+. ${LIBDIR}/libdatabase_maintain.sh
 . ${LIBDIR}/libdatabase_query.sh
 . ${LIBDIR}/libdatabase_record.sh
-. ${LIBDIR}/libcommand.sh
+. ${LIBDIR}/libdeinstall.sh
+. ${LIBDIR}/libfileedit.sh
+. ${LIBDIR}/libmain.sh
+. ${LIBDIR}/libmessage.sh
+. ${LIBDIR}/libmisc.sh
+. ${LIBDIR}/liboptions.sh
+. ${LIBDIR}/libpkgsys.sh
 . ${LIBDIR}/libprogram.sh
 . ${LIBDIR}/libreinstall.sh
-. ${LIBDIR}/libdeinstall.sh
+. ${LIBDIR}/libstr.sh
+. ${LIBDIR}/libtemp.sh
+. ${LIBDIR}/libusage.sh
+
+. ${LIBDIR}/main/libcommand.sh
+. ${LIBDIR}/main/liboptions.sh
+. ${LIBDIR}/main/libtemp.sh
+. ${LIBDIR}/main/libusage.sh
 
+DBDIR=/var/tmp/${APPNAME}.db
+CONFFILE=${ETCDIR}/${PROGRAM}.conf
+PKGTOOLSCONF=${ETCDIR}/pkgtools.conf
+
+main_set_version
 misc_init_vardefs
 temp_trap_init
-DBDIR=/var/tmp/${APPNAME}.db
-CONFFILE=${MYPREFIX}/etc/${APPNAME}.conf
-PKGTOOLSCONF=${MYPREFIX}/etc/pkgtools.conf
 
 # ==================================================
 # ========= PARSING OPTIONS AND ARGUMENTS ==========
 # ==================================================
 
-# ============= Save arguments for upgraded restart =============
-options_dump_args "$@" > ${TMPDIR}/restart_command.sh
-
-# ============= Option check =============
-options_set_default
-
-options_getopts "$@" || :
-if [ $OPTIONS_ERRNO -eq 2 ]
-then
-       message_echo "INTERNAL ERROR: In parsing options" >&2
-       exit 1
-fi
-shift "${OPTIONS_SHIFT}"
-
-# ============= Argument check for no-command options =============
-if [ $opt_help_mode -ne 0 -o $opt_show_version = yes ]
-then
-       if [ $# -gt 0 ]
-       then
-               OPTIONS_ERRNO=1
-       fi
-fi
-
-# ============= Output usage if the case of a help mode or option/argument errors =============
-if [ $OPTIONS_ERRNO -ne 0 ]
-then
-       exit $OPTIONS_ERRNO
-elif [ $opt_help_mode -eq 1 ]
-then
-       usage_short
-       exit
-elif [ $opt_help_mode -eq 2 ]
-then
-       usage_long | less -r
-       exit
-fi
-
-# ============= Output version number =============
-if [ $opt_show_version = yes ]
-then
-       message_version
-       exit
-fi
-
-# ============= Set up variables for environment of ports and packages =============
-conf_setup_ports_envs
-conf_setup_packages_envs
-
-# ============= Execute command operations before getting the temporary database ready =============
-command_exec_before_db_creation "$@"
-
-# ============= Creation of temporary database directory =============
-database_build_create
-
-# ============= Argument check for conventional runs =============
-command_parse_args "$@"
-shift "${COMMAND_SHIFT}"
-
-
-# ==================================================
-# ================== TOOLS SET UP ==================
-# ==================================================
-
-# ============= Termination messages during construction of the temporary database =============
-
-# Set termination messages
-temp_terminate_process_common ()
-{
-       local msg_where
-       [ $opt_batch_mode = yes ] && return
-       msg_where=`temp_get_msg_current_stage`
-       [ -n "$msg_where" ] && msg_where=" during $msg_where"
-       echo
-       if [ $errno -eq 130 ]
-       then
-               echo "INFO: Terminated at `message_timestamp`$msg_where."
-               echo
-               echo " You can restart this process from the terminated point by"
-       else
-               echo "INFO: Aborted at `message_timestamp`$msg_where."
-               echo
-               echo " You may restart this process from the aborted point by"
-       fi
-       echo "executing without options or arguments as:"
-       if [ -n "$COMMAND_RESTART" ]
-       then
-               echo "  ${APPNAME} $COMMAND_RESTART"
-       else
-               echo "  ${APPNAME}"
-       fi
-}
-
-temp_terminate_process ()
-{
-       local tmp_msg
-       tmp_msg=${TMPDIR}/temp_terminate_process:msg
-       [ $errno -eq 0 -o $opt_batch_mode = yes ] && return
-       temp_terminate_process_common
-       [ -n "$COMMAND_RESTART" ] && return
-       cat > $tmp_msg << eof
- Instead, if you only want to construct the temporary database so as to stop before the actual reinstallation, execute as:
-  ${APPNAME} prepare
-eof
-       message_cat "$tmp_msg"
-}
-
-# ============= Opening title =============
-
-message_credit
-[ $COMMAND_MODE = do -o $COMMAND_MODE = redo -o $COMMAND_MODE = forget ] && \
-       message_opening_notice
-message_echo
-
-# ============= Execute command operations which do not need package tools =============
-
-command_exec_without_pkgtools "$@"
-misc_is_superuser_privilege && touch "${DBDIR}/in_use"
-
-# ============= Definition of environment dependent functions =============
-
-pkgsys_def_pkgtools
-
-# ============= Option settings =============
-
-# Execute command operations which are not affected by saved option settings
-command_exec_irrespective_of_saved_options "$@"
+main_parse_options_arguments "$@"
 
-# Load, renew and save option values
-optcomb_err=0
-options_chk_invalid_optvals_renewal non_renewable || optcomb_err=$?
-if [ \( $opt_reload_conf = yes -o $opt_reset_targets = yes \) -a "x$COMMAND_MODE" != xredo ]
-then
-       message_echo "ERROR: Options -L and -N are available only in the initial run of redo command." >&2
-       message_echo >&2
-       optcomb_err=1
-fi
-if [ $opt_batch_ports_only = yes -a $opt_interactive_ports_only = yes ]
-then
-       message_echo "ERROR: Options -A and -I conflict with each other." >&2
-       message_echo >&2
-       optcomb_err=1
-fi
-if [ -e "${DBDIR}/saved_options.sh" ]
-then
-       {
-               options_renewed_optvals M renewable_anytime || optcomb_err=$?
-               options_renewed_optvals N renewable_in_redo_on_target || optcomb_err=$?
-               options_renewed_optvals L renewable_in_redo_on_conf || optcomb_err=$?
-       } > ${TMPDIR}/renewed_optvals.sh
-       [ $optcomb_err -eq 0 ] || exit $optcomb_err
-       . "${DBDIR}/saved_options.sh"
-       . "${TMPDIR}/renewed_optvals.sh"
-fi
-misc_is_superuser_privilege && misc_get_all_vardefs | options_filter saved > ${DBDIR}/saved_options.sh
+# ========================================================
+# ================== SET UP OF PARAMETERS ==================
+# ========================================================
 
-# Show option values
-if [ -e "${DBDIR}/saved_options.sh" -a $opt_batch_mode = no \
-       -a \( $COMMAND_MODE = do -o $COMMAND_MODE = redo \) ]
-then
-       message_echo "INFO: List of option values:"
-       message_echo "-----------------------------------------"
-       message_cat "${DBDIR}/saved_options.sh"
-       message_echo "-----------------------------------------"
-       message_echo
-fi
+main_setup_parameters "$@"
 
-# ============= Configurations =============
+# =================================================================================
+# ================== OPERATION WITHOUT PACKAGES MANAGEMENT TOOLS ==================
+# =================================================================================
 
-# Save the previous configuration if exists
-PROGRAM_DEPENDS=''
-_program_exec_and_record_completion__operation ()
-{
-       rm -rf "${DBDIR}/conf.prev"
-       [ -d "${DBDIR}/conf" ] && \
-               cp -Rp "${DBDIR}/conf" "${DBDIR}/conf.prev"
-       :
-}
-program_exec_and_record_completion SAVE_PREV_CONF
+main_operation_without_pkg_management_tools "$@"
 
-# Get complete configuration variable definitions by importing pkgtools.conf(5) if available
-PROGRAM_DEPENDS='SAVE_PREV_CONF'
-_program_exec_and_record_completion__operation ()
-{
-       local need_msg
-       need_msg=no
-       rm -rf "${DBDIR}/conf"
-       mkdir -p "${DBDIR}/conf"
-       [ "x`options_get_effective_opt_load_pkgtoolsconf 2> /dev/null`" != xno -a $opt_batch_mode = no ] \
-               && need_msg=yes
-       [ $need_msg = yes ] && \
-               message_section_title "Parsing pkgtools.conf (by using installed portupgrade)"
-       conf_get_complete_var_defs > ${DBDIR}/conf/complete_setup.sh
-       [ $need_msg = yes ] &&  { message_echo "===> ok"; message_echo; }
-       :
-}
-program_exec_and_record_completion GET_COMPLETE_CONF_VAR_DEF
-
-# Parse the configuration
-PROGRAM_DEPENDS='GET_COMPLETE_CONF_VAR_DEF'
-_program_exec_and_record_completion__operation ()
-{
-       message_section_title "Parsing the configuration"
-       conf_manipulate_available_var_defs
-       . "${DBDIR}/conf/manipulated_defs.sh"
-       # ALT_MOVED_*
-       conf_build_effective_MOVED
-       # Environmental variables
-       conf_setup_effective_env > ${DBDIR}/conf/setenv.sh
-       . "${DBDIR}/conf/setenv.sh"
-       # HOLD_*
-       conf_parse_vars_for_each_port_glob HOLD
-       str_escape_regexp_filter < ${DBDIR}/conf/HOLD:PORTS.parsed \
-               | sed 's/^/^/;s/$/$/' > ${DBDIR}/conf/HOLD_PORTS.grep_pattern
-       # TABOO_*
-       conf_parse_vars_for_each_port_glob TABOO
-       fileedit_combine_lists "${DBDIR}/conf/TABOO:PORTS.parsed" "${DBDIR}/taboo.list" \
-               > ${DBDIR}/taboo.all.list
-       # NOPKG_*
-       conf_parse_vars_for_each_port_glob NOPKG
-       # REPLACE_*
-       conf_build_replacement_patterns_from_REPLACE
-       # MARG_*
-       conf_parse_vars_for_each_port_glob_with_bound_val MARG TARGET DEF
-       # MENV_*
-       conf_parse_vars_for_each_port_glob_with_bound_val MENV TARGET DEF
-       # BEFOREBUILD_*
-       conf_parse_vars_for_each_port_glob_with_bound_val BEFOREBUILD TARGET COMMAND
-       # BEFOREDEINSTALL_*
-       conf_parse_vars_for_each_port_glob_with_bound_val BEFOREDEINSTALL TARGET COMMAND
-       # AFTERINSTALL_*
-       conf_parse_vars_for_each_port_glob_with_bound_val AFTERINSTALL TARGET COMMAND
-       message_echo
-}
-program_exec_and_record_completion PARSE_CONF
-
-. "${DBDIR}/conf/setenv.sh"
+# ===================================================
+# ================== SET UP OF TOOLS ==================
+# ===================================================
 
 # ============= Upgrade of tools =============
 
-# Execute command operations which should be done without upgrade of tools
-command_exec_before_tools_upgrade "$@"
-
-# Check whether the temporary database is newer than the ports tree and refresh if so
-database_build_refresh_if_obsolete
-
-# Get the port origin for this utility if installed by port
+# Get the flavored port origin for this utility if installed by port
 MYPORTORIGIN=`pkgsys_get_my_origin 2> /dev/null` || :
 
 # Collect all installed packages
-PROGRAM_DEPENDS=''
-_program_exec_and_record_completion__operation ()
-{
-       local tmp_installed_ports tmp_installed_pkgs
-       message_section_title "Collecting all installed packages"
-       if [ -e "${DBDIR}/installed_ports.inspected" ]
-       then
-               if ! [ "${DBDIR}/installed_ports" -ot "${DBDIR}/initial" -a "${DBDIR}/installed_ports:pkg_vs_origin.tbl" -ot "${DBDIR}/initial" ]
-               then
-                       find "${DBDIR}/initial" -depth 2 -type d \
-                               | sed -E 's|.*/([^/]+/[^/]+)$|\1|' > ${DBDIR}/installed_ports || :
-                       while read origin
-                       do
-                               pkg=`cat "${DBDIR}/initial/$origin/installed_version" 2>/dev/null` || continue
-                               printf '%s\t%s\n' "$origin" "$pkg"
-                       done < ${DBDIR}/installed_ports > ${DBDIR}/installed_ports:pkg_vs_origin.tbl
-               fi
-       else
-               pkg_info_qoa > ${DBDIR}/installed_ports
-               pkg_info_gen_pkg_origin_table
-       fi
-       str_escape_regexp_filter < "${DBDIR}/installed_ports" \
-               | sed 's/^/^/; s/$/$/' > ${DBDIR}/installed_ports.grep_pattern
-       message_echo
-}
-program_exec_and_record_completion COLLECT_ALL_INSTALLED_PACKAGES
+main_collect_all_installed_packages
 
 # Preliminary inspection of tools which have to be up-to-date
-# (No need depend on PARSE_CONF because INSPECT_ALL_DEPENDENCIES will take the task.)
-PROGRAM_DEPENDS=
-_program_exec_restartable_loop_operation__routine ()
-{
-       local origin
-       origin=$1
-       database_build_inspect_dependencies "$origin"
-}
-_program_exec_and_record_completion__operation ()
-{
-       local DEPTH_INDEX
-       message_section_title "Preliminary inspection of tools which have to be up-to-date"
-       {
-               [ "$PKGSYS_USE_PKGNG" = yes ] && pkgsys_portsmgmt_pkg
-               pkgsys_is_dialog4ports_used && pkgsys_portsmgmt_dialog4ports
-               [ -n "$MYPORTORIGIN" ] && echo "$MYPORTORIGIN"
-       } 2> /dev/null > ${DBDIR}/stage.loop_list/tools_to_inspect
-       DEPTH_INDEX='--'
-       program_exec_restartable_loop_operation tools_to_inspect
-       database_build_post_inspect_dependencies
-       message_echo
-}
-program_exec_and_record_completion PRELIMINARY_INSPECTION_OF_TOOLS
+main_preliminary_inspection_of_tools
 
 # Upgrade of pkg(8) if new
-# (No need depend on PARSE_CONF because REINSTALLATION will take the task.)
-if [ \( "$COMMAND_MODE" = do -o "$COMMAND_MODE" = redo \) \
-       -a $opt_dry_run = no -a $opt_suppress_pkgtools_upadte = no \
-       -a "$PKGSYS_USE_PKGNG" = yes ]
-then
-       PROGRAM_DEPENDS='PRELIMINARY_INSPECTION_OF_TOOLS'
-       _program_exec_and_record_completion__operation ()
-       {
-               local _MSG_CURRENT_STAGE_general
-               _MSG_CURRENT_STAGE_general="pkg(8) upgrade"
-               temp_set_msg_current_stage "${_MSG_CURRENT_STAGE_general}"
-               message_section_title "Upgrade of `pkgsys_portsmgmt_pkg` if new"
-               touch "${DBDIR}/target_all"
-               reinstall_exec `pkgsys_portsmgmt_pkg`
-               reinstall_restore_conflicts
-               rm -f "${DBDIR}/target_all"
-               temp_set_msg_current_stage
-               message_echo
-       }
-       program_exec_and_record_completion UPGRADE_PKGNG
-fi
+main_upgrade_pkg8_if_new
 
 # Upgrade of dialog4ports(1) if new
-# (No need depend on PARSE_CONF because REINSTALLATION will take the task.)
-if [ \( "$COMMAND_MODE" = do -o "$COMMAND_MODE" = redo \) \
-       -a $opt_dry_run = no -a $opt_suppress_pkgtools_upadte = no ] \
-       && pkgsys_is_dialog4ports_used
-then
-       PROGRAM_DEPENDS='PRELIMINARY_INSPECTION_OF_TOOLS'
-       _program_exec_and_record_completion__operation ()
-       {
-               local _MSG_CURRENT_STAGE_general
-               _MSG_CURRENT_STAGE_general="dialog4ports(1) upgrade"
-               temp_set_msg_current_stage "${_MSG_CURRENT_STAGE_general}"
-               message_section_title "Upgrade of `pkgsys_portsmgmt_dialog4ports` if new"
-               touch "${DBDIR}/target_all"
-               reinstall_exec `pkgsys_portsmgmt_dialog4ports`
-               reinstall_restore_conflicts
-               rm -f "${DBDIR}/target_all"
-               temp_set_msg_current_stage
-               message_echo
-       }
-       program_exec_and_record_completion UPGRADE_DIALOG4PORTS
-fi
+main_upgrade_dialog4ports1_if_new
 
 # Upgrade of this utility if new
-# (No need depend on PARSE_CONF because REINSTALLATION will take the task.)
-if [ \( "$COMMAND_MODE" = do -o "$COMMAND_MODE" = redo \) \
-       -a $opt_dry_run = no -a $opt_suppress_self_upadte = no \
-       -a -n "$MYPORTORIGIN" ]
-then
-       PROGRAM_DEPENDS='PRELIMINARY_INSPECTION_OF_TOOLS'
-       _program_exec_and_record_completion__operation ()
-       {
-               local _MSG_CURRENT_STAGE_general
-               _MSG_CURRENT_STAGE_general="pkgng upgrade"
-               temp_set_msg_current_stage "${_MSG_CURRENT_STAGE_general}"
-               message_section_title "Upgrade of this utility if new"
-               touch "${DBDIR}/target_all"
-               reinstall_exec "$MYPORTORIGIN"
-               reinstall_restore_conflicts
-               rm -f "${DBDIR}/target_all"
-               temp_set_msg_current_stage
-               message_echo
-       }
-       program_exec_and_record_completion UPGRADE_SELF
-fi
-
-if [ "x`${APPNAME} -aV 2> /dev/null`" != "x$MYVERSION" ]
-then
-       message_echo "INFO: ${APPNAME} is upgraded and the temporary database needs refresh."
-       database_build_clean_for_self_upgrade || :
-       message_echo "INFO: Restarting with the new version."
-       message_echo
-       temp_trap_for_invoking_new_version
-       . "${TMPDIR}"/restart_command.sh
-       exit
-fi
+main_self_upgrade
 
 
 # ==================================================
@@ -436,1086 +105,23 @@ fi
 
 # ============= Correspondence to configuration changes =============
 
-# Patch to the temporary database by reflecting changes in configuration
-PROGRAM_DEPENDS='PARSE_CONF'
-_program_exec_and_record_completion__operation ()
-{
-       local tmpfile_diff tmpfile_old tmpfile_new key
-       [ -d "${DBDIR}/conf.prev" ] || return 0
-       message_section_title "Patch to the temporary database by reflecting changes in configuration"
-       tmpfile_old=${TMPDIR}/PATCH_TO_TMPDB_REFLECT_CONF_CHANGES::old
-       tmpfile_new=${TMPDIR}/PATCH_TO_TMPDB_REFLECT_CONF_CHANGES::new
-       tmpfile_updated_ports=${TMPDIR}/PATCH_TO_TMPDB_REFLECT_CONF_CHANGES::updated_ports
-       if fileedit_manipulate_old_new_lines \
-               "${DBDIR}/conf.prev/setenv.sh" "${DBDIR}/conf/setenv.sh" "$tmpfile_old" "$tmpfile_new"
-       then
-               if grep -q -e ^LOCALBASE= -e ^LINUXBASE= -e ^PORTSDIR= "$tmpfile_old" "$tmpfile_new"
-               then
-                       message_echo "ERROR: Migration of the temporary database is unavailable because LOCALBASE, LINUXBASE or PORTSDIR was changed." >&2
-                       message_echo "        ${APPNAME} clean" >&2
-                       message_echo "must be executed in advance." >&2
-                       exit 1
-               fi
-       fi
-       cut -s -d '|' -f 1,2 "${DBDIR}/conf.prev/MOVED_ALT.parsed" | tr '|' '\t' > ${TMPDIR}/MOVED_ALT.old
-       cut -s -d '|' -f 1,2 "${DBDIR}/conf/MOVED_ALT.parsed" | tr '|' '\t' > ${TMPDIR}/MOVED_ALT.new
-       if fileedit_manipulate_old_new_lines \
-               "${TMPDIR}/MOVED_ALT.old" "${TMPDIR}/MOVED_ALT.new" "$tmpfile_old" "$tmpfile_new"
-       then
-               cat "$tmpfile_old" "$tmpfile_new" | while read from to
-               do
-                       echo "$from"
-                       [ -n "$to" ] && echo "$to"
-               done
-       fi > $tmpfile_updated_ports
-       sort -u "${DBDIR}/conf/NOPKG:PORTS.parsed" 2> /dev/null > ${TMPDIR}/NOPKG:PORTS.parsed.new || :
-       sort -u "${DBDIR}/conf.prev/NOPKG:PORTS.parsed" 2> /dev/null > ${TMPDIR}/NOPKG:PORTS.parsed.old || :
-       diff "${TMPDIR}/NOPKG:PORTS.parsed.old" "${TMPDIR}/NOPKG:PORTS.parsed.new" | sed -n 's/^[<>] //p' >> $tmpfile_updated_ports
-       if fileedit_manipulate_old_new_lines \
-               "${DBDIR}/conf.prev/REPLACE.csv" "${DBDIR}/conf/REPLACE.csv" "$tmpfile_old" "$tmpfile_new"
-       then
-               cat "$tmpfile_old" "$tmpfile_new" | while read from to
-               do
-                       echo "$from"
-                       [ -n "$to" ] && echo "$to"
-               done
-       fi >> $tmpfile_updated_ports
-       [ `wc -l < $tmpfile_updated_ports` -gt 0 ] && rm -f "${DBDIR}/REPLACE.complete_sed_pattern"
-       [ -d "${DBDIR}/conf/each_port" ] && find "${DBDIR}/conf/each_port" -depth 2 \
-               | while read dbpath
-       do
-               origin=`str_dirpath_to_origin "$dbpath"`
-               dbpath_prev=${DBDIR}/conf.prev/each_port/$origin
-               diff -r "$dbpath_prev" "$dbpath" > /dev/null 2>&1 && continue
-               echo "$origin"
-       done >> $tmpfile_updated_ports
-       [ -d "${DBDIR}/conf.prev/each_port" ] && find "${DBDIR}/conf.prev/each_port" -depth 2 \
-               | while read dbpath_prev
-       do
-               origin=`str_dirpath_to_origin "$dbpath_prev"`
-               dbpath=${DBDIR}/conf/each_port/$origin
-               [ -d "$dbpath" ] && continue
-               echo "$origin"
-       done >> $tmpfile_updated_ports
-       if [ `wc -l < $tmpfile_updated_ports` -gt 0 ]
-       then
-               sort -u "$tmpfile_updated_ports" | while read origin
-               do
-                       database_build_patch_reconf "$origin"
-               done
-               program_deregister_stage_complete INSPECT_ALL_DEPENDENCIES
-       fi
-       message_echo
-}
-program_exec_and_record_completion PATCH_TO_TMPDB_REFLECT_CONF_CHANGES
+# Overlay onto the temporary database by reflecting changes in configuration
+main_reflect_conf_changes
 
 # ============= Database construction =============
 
-# Execute command operations which must be done before building the temporary database
-command_exec_before_building_tempdb "$@"
-
-# Meta process for redo
-PROGRAM_DEPENDS=''
-_program_exec_and_record_completion__operation ()
-{
-       rm -f "${DBDIR}/new_success_in_current_run"
-       [ "x$COMMAND_MODE" = xredo ] || return 0
-       message_echo "[REDO mode]"
-       message_echo
-}
-program_exec_and_record_completion REDO_INIT
-
-# Determine specified targets
-PROGRAM_DEPENDS=''
-_program_exec_and_record_completion__operation ()
-{
-       local tag level dbsuffix
-       message_section_title "Determining specified targets"
-       cat "${DBDIR}/stage.loop_list/target_itself.specified" \
-               "${DBDIR}/stage.loop_list/target_dependents.specified" \
-               "${DBDIR}/stage.loop_list/target_requirements.specified" \
-               "${DBDIR}/need.list" \
-               "${DBDIR}/targets_specified_so_far" 2> /dev/null \
-               | sort -u > ${DBDIR}/targets_specified_so_far.tmp
-       mv "${DBDIR}/targets_specified_so_far.tmp" "${DBDIR}/targets_specified_so_far"
-       rm -f "${DBDIR}/stage.loop_list/target_itself.specified" \
-               "${DBDIR}/stage.loop_list/target_dependents.specified" \
-               "${DBDIR}/stage.loop_list/target_requirements.specified"
-       if [ -n "$opt_target_itself$opt_target_dependents$opt_target_requirements" ]
-       then
-               options_select_new_ports_if_duplicated O \
-                       "${DBDIR}/stage.loop_list/target_itself.specified" "$opt_target_itself"
-               options_select_new_ports_if_duplicated t \
-                       "${DBDIR}/stage.loop_list/target_dependents.specified" "$opt_target_dependents"
-               options_select_new_ports_if_duplicated T \
-                       "${DBDIR}/stage.loop_list/target_requirements.specified" "$opt_target_requirements"
-               if [ `cat "${DBDIR}/stage.loop_list/target_itself.specified" \
-                       "${DBDIR}/stage.loop_list/target_dependents.specified" \
-                       "${DBDIR}/stage.loop_list/target_requirements.specified" | wc -l` -eq 0 ]
-               then
-                       message_echo "ERROR: No matching port for target globs." >&2
-                       message_echo >&2
-                       exit 1
-               fi
-               cat "${DBDIR}/stage.loop_list/target_itself.specified" \
-                       "${DBDIR}/stage.loop_list/target_dependents.specified" \
-                       "${DBDIR}/stage.loop_list/target_requirements.specified" \
-                       | sort -u > ${TMPDIR}/DETERMINE_SPECIFIED_TARGETS.reset
-               cat "${TMPDIR}/DETERMINE_SPECIFIED_TARGETS.reset" "${DBDIR}/need.list" 2> /dev/null \
-                       | sort -u > ${DBDIR}/need.list.tmp
-               mv "${DBDIR}/need.list.tmp" "${DBDIR}/need.list"
-               sort -u "${DBDIR}/need.list" "${DBDIR}/targets_specified_so_far" \
-                       > ${DBDIR}/targets_specified_so_far.tmp
-               mv "${DBDIR}/targets_specified_so_far.tmp" "${DBDIR}/targets_specified_so_far"
-               for tag in all run build none
-               do
-                       for level in direct full
-                       do
-                               dbsuffix=$tag.$level
-                               {
-                                       cat "${TMPDIR}/DETERMINE_SPECIFIED_TARGETS.reset"
-                                       cat "${DBDIR}/stage.loop_list/target_dependents.specified" | while read origin
-                                       do
-                                               nodedir=${DBDIR}/requires/$origin
-                                               cat "$nodedir/dependents.$dbsuffix" 2> /dev/null
-                                       done
-                                       cat "${DBDIR}/stage.loop_list/target_requirements.specified" | while read origin
-                                       do
-                                               nodedir=${DBDIR}/requires/$origin
-                                               cat "$nodedir/requirements.$dbsuffix" 2> /dev/null
-                                       done
-                               } | sort -u | while read origin
-                               do
-                                       fileedit_rm_a_line "$origin" "${DBDIR}/success.$dbsuffix.list"
-                                       fileedit_rm_a_line "$origin" "${DBDIR}/todo_after_requirements_succeed.$dbsuffix.list"
-                                       rm -f "${DBDIR}/requires/$origin/succeeded_once"
-                               done
-                       done
-               done
-       fi
-       message_echo
-}
-program_exec_and_record_completion DETERMINE_SPECIFIED_TARGETS
-
-# Show specified targets
-if [ -n "$opt_target_itself$opt_target_dependents$opt_target_requirements" -a $opt_batch_mode = no ]
-then
-       message_echo "INFO: (Re/de-)installation will be carried out only for the targets:"
-       echo
-       if [ `wc -l < ${DBDIR}/stage.loop_list/target_itself.specified` -gt 0 ]
-       then
-               message_echo "[Targets only]"
-               echo "----------------------------------------"
-               cat "${DBDIR}/stage.loop_list/target_itself.specified"
-               echo "----------------------------------------"
-               echo
-       fi
-       if [ `wc -l < ${DBDIR}/stage.loop_list/target_dependents.specified` -gt 0 ]
-       then
-               message_echo "[Targets with their `options_get_dependency_msgterm` dependents]"
-               echo "----------------------------------------"
-               cat "${DBDIR}/stage.loop_list/target_dependents.specified"
-               echo "----------------------------------------"
-               echo
-       fi
-       if [ `wc -l < ${DBDIR}/stage.loop_list/target_requirements.specified` -gt 0 ]
-       then
-               message_echo "[Targets with their `options_get_dependency_msgterm` requirements]"
-               echo "----------------------------------------"
-               cat "${DBDIR}/stage.loop_list/target_requirements.specified"
-               echo "----------------------------------------"
-               echo
-       fi
-fi
-
-# Determine all target ports
-PROGRAM_DEPENDS='DETERMINE_SPECIFIED_TARGETS COLLECT_ALL_INSTALLED_PACKAGES'
-_program_exec_and_record_completion__operation ()
-{
-       message_section_title "Determining all target ports"
-       {
-               if [ $opt_only_target_scope = no ]
-               then
-                       cat "${DBDIR}/installed_ports" 2> /dev/null || :
-               fi
-               cat "${DBDIR}/stage.loop_list/target_itself.specified" || :
-               cat "${DBDIR}/stage.loop_list/target_dependents.specified" || :
-               cat "${DBDIR}/stage.loop_list/target_requirements.specified" || :
-               cat "${DBDIR}/targets_specified_so_far" || :
-       }  2> /dev/null | sort -u > "${DBDIR}/stage.loop_list/ports_to_inspect"
-       message_echo
-}
-program_exec_and_record_completion DETERMINE_ALL_TARGET_PORTS
-
-# Inspection of all dependencies
-PROGRAM_DEPENDS='PARSE_CONF DETERMINE_ALL_TARGET_PORTS'
-_program_exec_restartable_loop_operation__routine ()
-{
-       local origin
-       origin=$1
-       database_build_inspect_dependencies "$origin"
-}
-_program_exec_and_record_completion__operation ()
-{
-       local DEPTH_INDEX 
-       message_section_title "Inspecting dependencies of the all installed packages"
-       [ $opt_only_target_scope = no -a -n "$opt_target_itself$opt_target_dependents$opt_target_requirements" ] && \
-               message_echo "INFO: Ports which seem irrelevant to the targets are also inspected in order to get complete information."
-       DEPTH_INDEX='--'
-       program_exec_restartable_loop_operation ports_to_inspect
-       database_build_post_inspect_dependencies
-       message_echo
-}
-program_exec_and_record_completion INSPECT_ALL_DEPENDENCIES
-
-# Convert dependency-lists to actual ones
-PROGRAM_DEPENDS='INSPECT_ALL_DEPENDENCIES'
-_program_exec_restartable_loop_operation__routine ()
-{
-       local origin table dbtag level tag target
-       origin=$1
-       for table in dependents requirements
-       do
-               for dbtag in requires obsolete
-               do
-                       for level in direct full
-                       do
-                               for tag in all run build
-                               do
-                                       target=${DBDIR}/$dbtag/$origin/${table}.${tag}.${level}
-                                       if [ -e "$target.src" ]
-                                       then
-                                               sed -E -f "${DBDIR}/REPLACE.complete_sed_pattern" "$target.src" \
-                                                       | grep -v '^$' | sort -u > $target.tmp
-                                               [ -e "$target" ] && ! diff "$target.tmp" "$target" > /dev/null \
-                                                       && echo "$origin" >> ${DBDIR}/update_dependencies
-                                               mv "$target.tmp" "$target"
-                                       else
-                                               [ -e "$target" ] && echo "$origin" >> ${DBDIR}/update_dependencies
-                                               rm -f "$target"
-                                       fi
-                               done
-                       done
-               done
-       done
-}
-_program_exec_and_record_completion__operation ()
-{
-       message_section_title "Conversion of dependency-lists to actual ones"
-       program_exec_restartable_loop_operation convert_dependency_lists
-       sort -u "${DBDIR}/update_dependencies" > ${DBDIR}/update_dependencies.tmp
-       mv "${DBDIR}/update_dependencies.tmp" "${DBDIR}/update_dependencies"
-       str_escape_regexp_filter < ${DBDIR}/update_dependencies \
-               | sed 's/^/^/; s/$/$/' > ${DBDIR}/update_dependencies.grep_pattern
-       for tag in all run build
-       do
-               ( cd "${DBDIR}/requires" && \
-                       find . -depth 3 -type f -name requirements.${tag}.full -or -name requirements.${tag}.full.orig ) \
-                       | sort -u \
-                       | sed 's|^./||;s|/[^/]*$||' \
-                       | grep -v -E -f "${DBDIR}/update_dependencies.grep_pattern" \
-                       | str_escape_regexp_filter | sed 's/^/^/; s/$/$/' \
-                       > ${TMPDIR}/convert_requirements_list:full_complete.grep_pattern || :
-               ( cd "${DBDIR}/requires" && \
-                       find . -depth 3 -type f -name requirements.${tag}.direct -or -name requirements.${tag}.direct.orig ) \
-                       | sort -u \
-                       | sed 's|^./||;s|/[^/]*$||' \
-                       | grep -v -E -f "${TMPDIR}/convert_requirements_list:full_complete.grep_pattern" \
-                       > ${DBDIR}/stage.loop_list/complete_recursive_${tag}time_reqlists || :
-       done
-       for inspected_level_tmp in direct node
-       do
-               cat "${DBDIR}/ports.inspected.${inspected_level_tmp}.list" || :
-       done 2> /dev/null | sort -u > ${DBDIR}/stage.loop_list/trim_dependency_lists_rm_uninspected_ports
-       find "${DBDIR}/requires" -depth 2 -type d > ${DBDIR}/stage.loop_list/inspect_dependent
-       [ -e "${DBDIR}/dependents_files" ] && \
-               mv "${DBDIR}/dependents_files" "${DBDIR}/dependents_files.prev"
-       rm -f "${DBDIR}/stage.loop_list/make_dependents_lists_unique.tmp" "${DBDIR}/dependents_files.tmp"
-       message_echo
-}
-program_exec_and_record_completion CONVERT_REQUIREMENTS_LIST
-
-# Completion of recursive requirement lists
-for _REQUIREMENT_LISTS_tag in all run build
-do
-       PROGRAM_DEPENDS='CONVERT_REQUIREMENTS_LIST'
-       _program_exec_restartable_loop_operation__routine ()
-       {
-               local tag dbpath origin suffix
-               tag=${_REQUIREMENT_LISTS_tag}
-               dbpath=$1
-               origin=`str_dirpath_to_origin "$dbpath"`
-               for suffix in '' .orig
-               do
-                       database_build_get_complete_recursive_dependency "$tag" "$origin" "$suffix" > /dev/null
-               done
-       }
-       _program_exec_and_record_completion__operation ()
-       {
-               local tag
-               tag=${_REQUIREMENT_LISTS_tag}
-               message_section_title "Completion of ${tag}-time requirement lists"
-               program_exec_restartable_loop_operation complete_recursive_${tag}time_reqlists
-               message_echo
-       }
-       program_exec_and_record_completion RECURSIVE_REQUIREMENT_LISTS:${_REQUIREMENT_LISTS_tag}
-done
-
-# Trim dependency lists by removing uninspected ports
-if [ $opt_only_target_scope = yes ]
-then
-       PROGRAM_DEPENDS='INSPECT_ALL_DEPENDENCIES CONVERT_REQUIREMENTS_LIST'
-       _program_exec_restartable_loop_operation__routine ()
-       {
-               local dbpath tag level srcdb
-               dbpath=$1
-               for tag in all run build
-               do
-                       for level in direct full
-                       do
-                               srcdb=requirements.${tag}.${level}
-                               [ -e "$dbpath/$srcdb" ] || continue
-                               grep -E -f "${DBDIR}/inspected_ports.grep_pattern" "$dbpath/$srcdb" \
-                                       > $dbpath/$srcdb.tmp || :
-                               mv "$dbpath/$srcdb.tmp" "$dbpath/$srcdb"
-                       done
-               done
-       }
-       _program_exec_and_record_completion__operation ()
-       {
-               message_section_title "Trimming dependency lists by removing uninspected ports"
-               program_exec_restartable_loop_operation trim_dependency_lists_rm_uninspected_ports
-               message_echo
-       }
-       program_exec_and_record_completion TRIM_DEPENDENCY_LISTS_RM_UNINSPECTED_PORTS
-fi
-
-# Inspection of dependents
-PROGRAM_DEPENDS='INSPECT_ALL_DEPENDENCIES CONVERT_REQUIREMENTS_LIST TRIM_DEPENDENCY_LISTS_RM_UNINSPECTED_PORTS'
-_program_exec_restartable_loop_operation__routine ()
-{
-       local dbpath origin tag level suffix srcdb dstdb
-       dbpath=$1
-       origin=`str_dirpath_to_origin "$dbpath"`
-       for tag in all run build
-       do
-               for suffix in '' .orig
-               do
-                       for level in direct full
-                       do
-                               srcdb=requirements.${tag}.${level}${suffix}
-                               [ -e "$dbpath/$srcdb" ] || continue
-                               dstdb=dependents.${tag}.${level}${suffix}
-                               while read origin_requirement
-                               do
-                                       dstpath=${DBDIR}/requires/$origin_requirement
-                                       echo "$dstpath/$dstdb" >> ${DBDIR}/dependents_files.tmp
-                                       [ "$dstpath/$dstdb" -nt "$dbpath/$srcdb" ] && continue
-                                       [ -d "$dstpath" ] || mkdir -p "$dstpath"
-                                       echo "$origin" >> $dstpath/$dstdb.raw
-                                       echo "$dstpath/$dstdb" >> ${DBDIR}/stage.loop_list/make_dependents_lists_unique.tmp
-                               done < $dbpath/$srcdb
-                       done
-                       srcdb=ignored_requirements.${tag}${suffix}
-                       [ -e "$dbpath/$srcdb" ] || continue
-                       dstdb=ignored_dependents.${tag}${suffix}
-                       while read origin_requirement
-                       do
-                               dstpath=${DBDIR}/requires/$origin_requirement
-                               echo "$dstpath/$dstdb" >> ${DBDIR}/ignored_dependents_files.tmp
-                               [ "$dstpath/$dstdb" -nt "$dbpath/$srcdb" ] && continue
-                               [ -d "$dstpath" ] || mkdir -p "$dstpath"
-                               echo "$origin" >> $dstpath/$dstdb.raw
-                               echo "$dstpath/$dstdb" >> ${DBDIR}/stage.loop_list/make_ignored_dependents_lists_unique.tmp
-                       done < $dbpath/$srcdb
-               done
-       done
-}
-_program_exec_and_record_completion__operation ()
-{
-       local dbrequires_valesc
-       message_section_title "Inspection of dependents"
-       dbrequires_valesc=`str_escape_replaceval "${DBDIR}/requires/"`
-       program_exec_restartable_loop_operation inspect_dependent
-       for dbtype in dependents ignored_dependents
-       do
-               sort -u "${DBDIR}/stage.loop_list/make_${dbtype}_lists_unique.tmp" 2> /dev/null \
-                       > ${DBDIR}/stage.loop_list/make_${dbtype}_lists_unique || :
-               sort -u "${DBDIR}/${dbtype}_files.tmp" 2> /dev/null > ${DBDIR}/${dbtype}_files || :
-               [ -e "${DBDIR}/make_${dbtype}_lists_unique.prev" ] && \
-                       fileedit_manipulate_old_lines "${DBDIR}/${dbtype}_files.prev" "${DBDIR}/${dbtype}_files" \
-                       | xargs rm -f
-       done
-       message_echo
-}
-program_exec_and_record_completion INSPECT_DEPENDENTS
-
-# Remove duplicated lines in dependents lists
-PROGRAM_DEPENDS='CONVERT_REQUIREMENTS_LIST INSPECT_DEPENDENTS'
-_program_exec_restartable_loop_operation__routine ()
-{
-       local dbpath tag level dstdb
-       dstdb=$1
-       cat "$dstdb" "$dstdb.raw" 2> /dev/null | sort -u > $dstdb.tmp
-       mv "$dstdb.tmp" "$dstdb"
-       rm -f "$dstdb.raw"
-}
-_program_exec_and_record_completion__operation ()
-{
-       local dbrequires_valesc
-       message_section_title "Removing duplicated items in dependents lists"
-       program_exec_restartable_loop_operation make_dependents_lists_unique
-       message_echo
-}
-program_exec_and_record_completion MAKE_DEPENDENTS_LISTS_UNIQUE
-
-# Remove duplicated lines in ignored dependents lists
-PROGRAM_DEPENDS='CONVERT_REQUIREMENTS_LIST INSPECT_DEPENDENTS'
-_program_exec_restartable_loop_operation__routine ()
-{
-       local dbpath tag level dstdb
-       dstdb=$1
-       cat "$dstdb" "$dstdb.raw" 2> /dev/null | sort -u > $dstdb.tmp
-       mv "$dstdb.tmp" "$dstdb"
-       rm -f "$dstdb.raw"
-}
-_program_exec_and_record_completion__operation ()
-{
-       local dbrequires_valesc
-       message_section_title "Removing duplicated items in ignored dependents lists"
-       program_exec_restartable_loop_operation make_ignored_dependents_lists_unique
-       message_echo
-}
-program_exec_and_record_completion MAKE_IGNORED_DEPENDENTS_LISTS_UNIQUE
-
-# Preparation of target attribute information
-for _TARGET_ATTR_INFO_table in requirements dependents itself
-do
-       [ `cat "${DBDIR}/stage.loop_list/target_${_TARGET_ATTR_INFO_table}.replaced.specified" 2> /dev/null \
-               | wc -l` -gt 0 ] || continue
-       PROGRAM_DEPENDS='DETERMINE_SPECIFIED_TARGETS CONVERT_REQUIREMENTS_LIST'
-       _program_exec_restartable_loop_operation__routine ()
-       {
-               local origin dbtargets_valesc table
-               origin=$1
-               dbtargets_valesc=`str_escape_replaceval "${DBDIR}/targets/"`
-               table=${_TARGET_ATTR_INFO_table}
-               for database in requires initial
-               do
-                       dbpath=${DBDIR}/$database/$origin
-                       dstpath=${DBDIR}/targets/$origin
-                       [ -d "$dstpath" ] || mkdir -p "$dstpath"
-                       touch "$dstpath/target_itself"
-                       echo "$origin" >> ${DBDIR}/all_targets.lst
-                       [ $table = itself ] && continue
-                       for tag in all run build
-                       do
-                               for level in direct full
-                               do
-                                       srcdb=${table}.${tag}.${level}
-                                       dstdb=target_${database}_${table}.${tag}.${level}
-                                       [ -e "$dbpath/$srcdb" ] || continue
-                                       cat "$dbpath/$srcdb" >> ${DBDIR}/all_targets.lst
-                                       sed -E "s/^/$dbtargets_valesc/; s|$|/$dstdb|" "$dbpath/$srcdb" \
-                                               | fileedit_add_a_line_to_files_if_new "$origin"
-                               done
-                       done
-               done
-       }
-       _program_exec_and_record_completion__operation ()
-       {
-               local table
-               table=${_TARGET_ATTR_INFO_table}
-               message_section_title "Preparation of target attribute information for dependency [$table]"
-               program_exec_restartable_loop_operation target_$table.replaced.specified
-               message_echo
-       }
-       program_exec_and_record_completion TARGET_ATTR_INFO:${_TARGET_ATTR_INFO_table}
-done
-
-# Post-process after the preparation of target attribute information
-PROGRAM_DEPENDS='MAKE_DEPENDENTS_LISTS_UNIQUE MAKE_IGNORED_DEPENDENTS_LISTS_UNIQUE TARGET_ATTR_INFO:requirements TARGET_ATTR_INFO:dependents'
-_program_exec_and_record_completion__operation ()
-{
-       message_section_title "Post-process after the preparation of target attribute information"
-       sort -u "${DBDIR}/all_targets.lst" 2> /dev/null \
-               | grep -E -f "${DBDIR}/inspected_ports.grep_pattern" \
-               | sed -E -f "${DBDIR}/REPLACE.complete_sed_pattern" \
-               > ${DBDIR}/all_targets.lst.tmp || :
-       mv "${DBDIR}/all_targets.lst.tmp" "${DBDIR}/all_targets.lst"
-       find "${DBDIR}/targets" -depth 2 -type d > ${DBDIR}/stage.loop_list/build_complement_to_new_dependents_for_targets 2> /dev/null || :
-       {
-               cat "${DBDIR}/all_targets.lst" "${DBDIR}/need.with_replaced.list" 2> /dev/null || :
-               find "${DBDIR}/requires" -depth 3 -type f -name installed_version \
-                       | sed -E 's|.*/([^/]+/[^/]+)/[^/]*$|\1|'
-       } | sort -u > ${DBDIR}/stage.loop_list/inspect_necessity
-       cp /dev/null "${DBDIR}/stage.loop_list/parse_target_attr_info"
-       find -E "${DBDIR}/requires" -depth 3 -type f -regex '.*/necessary_port\.(direct|full)$' -delete
-       message_echo
-}
-program_exec_and_record_completion TARGET_ATTR_INFO_POSTPROCESS
-
-# Build of data on complement to new dependents for target attribute information
-PROGRAM_DEPENDS='TARGET_ATTR_INFO_POSTPROCESS TARGET_ATTR_INFO:requirements TARGET_ATTR_INFO:dependents CONVERT_REQUIREMENTS_LIST'
-_program_exec_restartable_loop_operation__routine ()
-{
-       local dbpath origin
-       dbpath=$1
-       origin=`str_dirpath_to_origin "$dbpath"`
-       database_build_complement_to_new_dependents_for_targets "$origin"
-}
-_program_exec_and_record_completion__operation ()
-{
-       message_section_title "Build of data on complement to new dependents for target attribute information"
-       program_exec_restartable_loop_operation build_complement_to_new_dependents_for_targets
-       sort -u "${DBDIR}/stage.loop_list/parse_target_attr_info" > ${DBDIR}/stage.loop_list/parse_target_attr_info.tmp
-       mv "${DBDIR}/stage.loop_list/parse_target_attr_info.tmp" "${DBDIR}/stage.loop_list/parse_target_attr_info"
-       message_echo
-}
-program_exec_and_record_completion COMPLEMENT_TO_NEW_DEPENDENTS_FOR_TARGET_ATTR_INFO
-
-# Parse target attribute information
-PROGRAM_DEPENDS='COMPLEMENT_TO_NEW_DEPENDENTS_FOR_TARGET_ATTR_INFO'
-_program_exec_restartable_loop_operation__routine ()
-{
-       local dbpath origin
-       dbpath=$1
-       origin=`str_dirpath_to_origin "$dbpath"`
-       database_build_target_attributes "$origin"
-}
-_program_exec_and_record_completion__operation ()
-{
-       message_section_title "Parsing target attribute information"
-       program_exec_restartable_loop_operation parse_target_attr_info
-       message_echo
-}
-program_exec_and_record_completion PARSE_TARGET_ATTR_INFO
-
-# Inspection of necessity
-PROGRAM_DEPENDS='TARGET_ATTR_INFO_POSTPROCESS RECURSIVE_REQUIREMENT_LISTS:run RECURSIVE_REQUIREMENT_LISTS:build INSPECT_ALL_DEPENDENCIES'
-_program_exec_restartable_loop_operation__routine ()
-{
-       local origin
-       origin=$1
-       for level in direct full
-       do
-               database_build_inspect_necessity_for_only_new_upgrade "$origin" "$level"
-       done
-}
-_program_exec_and_record_completion__operation ()
-{
-       message_section_title "Inspection of necessity"
-       program_exec_restartable_loop_operation inspect_necessity
-       for level in direct full
-       do
-               find "${DBDIR}/requires" -depth 3 -type f -name "necessary_port.${level}" \
-                       > ${DBDIR}/stage.loop_list/necessary_ports.${level}
-       done
-       message_echo
-}
-program_exec_and_record_completion INSPECT_NECESSITY
-
-# Inspection of necessary upgrades
-for _NECESSARY_UPDATES_level in direct full
-do
-       PROGRAM_DEPENDS='INSPECT_NECESSITY INSPECT_ALL_DEPENDENCIES MAKE_DEPENDENTS_LISTS_UNIQUE MAKE_IGNORED_DEPENDENTS_LISTS_UNIQUE'
-       _program_exec_restartable_loop_operation__routine ()
-       {
-               local markerpath level dbpath origin tag
-               markerpath=$1
-               level=${_NECESSARY_UPDATES_level}
-               dbpath=`dirname "$markerpath"`
-               origin=`str_dirpath_to_origin "$dbpath"`
-               database_query_does_a_port_need_update "$origin" || return 0
-               for tag in all run build none
-               do
-                       touch "$dbpath/necessary_upgrade.$tag.${level}"
-                       [ -e "$dbpath/dependents.$tag.${level}" -o "$dbpath/ignored_dependents.$tag" ] || continue
-                       cat "$dbpath/dependents.$tag.${level}" "$dbpath/ignored_dependents.$tag" 2> /dev/null | \
-                               while read origin_dependent
-                               do
-                                       touch "${DBDIR}/requires/$origin_dependent/necessary_upgrade.$tag.${level}"
-                               done
-               done
-       }
-       _program_exec_and_record_completion__operation ()
-       {
-               local level
-               level=${_NECESSARY_UPDATES_level}
-               message_section_title "Inspection of necessary upgrades at the $level level"
-               program_exec_restartable_loop_operation necessary_ports.${level}
-               message_echo
-       }
-       program_exec_and_record_completion NECESSARY_UPDATES:${_NECESSARY_UPDATES_level}
-done
-
-# Preparation for inspection of new leaf ports
-if [ ! -e "${DBDIR}/inspected_ports_only_partially" ]
-then
-       PROGRAM_DEPENDS='INSPECT_ALL_DEPENDENCIES MAKE_DEPENDENTS_LISTS_UNIQUE MAKE_IGNORED_DEPENDENTS_LISTS_UNIQUE PARSE_CONF'
-       _program_exec_and_record_completion__operation ()
-       {
-               message_section_title "Preparation for inspection of new leaf ports"
-               find "${DBDIR}/requires" -depth 3 -type f -name dependents.all.full -or -name ignored_dependents.all \
-                       | sed -E 's|.*/([^/]+/[^/]+)/[^/]+$|\1|' \
-                       | sort -u > ${TMPDIR}/PREPARE_INSPECT_LEAF_PORTS:nonleaf_ports
-               sort -u "${DBDIR}/inspected_ports" > ${TMPDIR}/PREPARE_INSPECT_LEAF_PORTS:inspected_ports
-               fileedit_manipulate_new_lines \
-                       "${TMPDIR}/PREPARE_INSPECT_LEAF_PORTS:nonleaf_ports" \
-                       "${TMPDIR}/PREPARE_INSPECT_LEAF_PORTS:inspected_ports" \
-                       | grep -v -E -f "${DBDIR}/conf/HOLD_PORTS.grep_pattern" \
-                       > ${DBDIR}/stage.loop_list/leaf_ports_primary_candidates || :
-               cp /dev/null "${DBDIR}/grep.leaf_ports.pattern"
-               cp /dev/null "${DBDIR}/stage.loop_list/leaf_ports_secondary_candidates"
-               message_echo
-       }
-       program_exec_and_record_completion PREPARE_INSPECT_LEAF_PORTS
-fi
-
-# Inspection of new primary leaf ports
-if [ ! -e "${DBDIR}/inspected_ports_only_partially" ]
-then
-       PROGRAM_DEPENDS='INSPECT_ALL_DEPENDENCIES MAKE_DEPENDENTS_LISTS_UNIQUE MAKE_IGNORED_DEPENDENTS_LISTS_UNIQUE PREPARE_INSPECT_LEAF_PORTS PARSE_CONF'
-       _program_exec_restartable_loop_operation__routine ()
-       {
-               local origin origin_ini origin_esc dbpath origin_req
-               origin=$1
-               pkgsys_is_pkgtool "$origin" && return
-               dbpath=${DBDIR}/requires/$origin
-               origin_esc=`str_escape_regexp "$origin"`
-               grep -q -E "^$origin_esc$" "${DBDIR}/need.with_replaced.list" 2> /dev/null && return
-               if ! grep -q -E "^$origin_esc$" "${DBDIR}/noneed.list" 2> /dev/null
-               then
-                       if [ -e "$dbpath/initial_orig" ]
-                       then
-                               origin_ini=`cat "$dbpath/initial_orig"`
-                               [ -e "${DBDIR}/initial/$origin_ini/installed_version" \
-                                       -a `cat "${DBDIR}/initial/$origin_ini/dependents.all.full" 2> /dev/null | wc -l` -eq 0 ] \
-                                       && return
-                       fi
-                       [ -e "${DBDIR}/initial/$origin/installed_version" \
-                               -a `cat "${DBDIR}/initial/$origin/dependents.all.full" 2> /dev/null | wc -l` -eq 0 ] \
-                               && return
-               fi
-               if [ -e "$dbpath/requirements.all.full" -o -e "$dbpath/ignored_requirements.all" ]
-               then
-                       cat "$dbpath/requirements.all.full" "$dbpath/ignored_requirements.all" 2> /dev/null | \
-                               grep -v -E -f "${DBDIR}/conf/HOLD_PORTS.grep_pattern" | \
-                               fileedit_add_lines_if_new "${DBDIR}/stage.loop_list/leaf_ports_secondary_candidates" || :
-               fi
-               fileedit_add_a_line_if_new "^$origin_esc$" "${DBDIR}/grep.leaf_ports.pattern"
-       }
-       _program_exec_and_record_completion__operation ()
-       {
-               local num_leaves num_leaves_prev
-               message_section_title "Inspection of new primary leaf ports"
-               program_exec_restartable_loop_operation leaf_ports_primary_candidates
-               wc -l < ${DBDIR}/grep.leaf_ports.pattern | tr -d ' ' > ${DBDIR}/num_leaves
-               cp /dev/null "${DBDIR}/leaf_ports_secondary_candidates.new_requirements"
-               message_echo "  `cat "${DBDIR}/num_leaves"` primary leaf port(s) is/are found."
-               message_echo
-       }
-       program_exec_and_record_completion INSPECT_PRIMARY_LEAF_PORTS
-fi
-
-# Inspection of requirements of new leaf ports
-if [ ! -e "${DBDIR}/inspected_ports_only_partially" ]
-then
-       PROGRAM_DEPENDS='INSPECT_ALL_DEPENDENCIES MAKE_DEPENDENTS_LISTS_UNIQUE MAKE_IGNORED_DEPENDENTS_LISTS_UNIQUE INSPECT_PRIMARY_LEAF_PORTS PARSE_CONF'
-       _program_exec_and_record_completion__operation ()
-       {
-               local num_leaves num_leaves_prev num_inspect num_leaves_new
-               message_section_title "Inspection of requirements of new leaf ports"
-               message_echo "INFO: The inspection proceeds by iterative method."
-               while :
-               do
-                       _program_exec_restartable_loop_operation__routine ()
-                       {
-                               local origin origin_esc dbpath
-                               origin=$1
-                               pkgsys_is_pkgtool "$origin" && return
-                               dbpath=${DBDIR}/requires/$origin
-                               origin_esc=`str_escape_regexp "$origin"`
-                               grep -q -E "^$origin_esc$" "${DBDIR}/need.with_replaced.list" 2> /dev/null && return
-                               cat "$dbpath/dependents.all.full" "$dbpath/ignored_dependents.all"  2> /dev/null \
-                                       | grep -Eq -v -f "${DBDIR}/grep.leaf_ports.pattern" && return
-                               cat "$dbpath/requirements.all.full" "$dbpath/ignored_requirements.all" 2> /dev/null \
-                                       >> ${DBDIR}/leaf_ports_secondary_candidates.new_requirements || :
-                               fileedit_add_a_line_if_new "^$origin_esc$" "${DBDIR}/grep.leaf_ports.pattern"
-                       }
-                       program_exec_restartable_loop_operation leaf_ports_secondary_candidates
-                       num_leaves_prev=`cat "${DBDIR}/num_leaves"`
-                       num_leaves=`wc -l < ${DBDIR}/grep.leaf_ports.pattern | tr -d ' '`
-                       num_leaves_new=`echo $(($num_leaves-$num_leaves_prev)) | tr -d ' '`
-                       if [ $num_leaves_new -eq 0 ]
-                       then
-                               message_echo "  No more leaf port is found."
-                               message_echo "  $num_leaves leaf port(s) is/are found in total."
-                               break
-                       fi
-                       {
-                               grep -E -v -f "${DBDIR}/grep.leaf_ports.pattern" \
-                                       "${DBDIR}/stage.loop_list/leaf_ports_secondary_candidates" || :
-                               cat "${DBDIR}/leaf_ports_secondary_candidates.new_requirements" || :
-                       } | grep -v -E -f "${DBDIR}/conf/HOLD_PORTS.grep_pattern" | sort -u \
-                               > ${DBDIR}/stage.loop_list/leaf_ports_secondary_candidates.tmp || :
-                       program_reset_loop_for_stage INSPECT_REQUIREMENTS_OF_LEAF_PORTS
-                       mv "${DBDIR}/stage.loop_list/leaf_ports_secondary_candidates.tmp" \
-                               "${DBDIR}/stage.loop_list/leaf_ports_secondary_candidates"
-                       cp /dev/null "${DBDIR}/leaf_ports_secondary_candidates.new_requirements"
-                       echo "$num_leaves" > ${DBDIR}/num_leaves
-                       num_inspect=`wc -l < ${DBDIR}/stage.loop_list/leaf_ports_secondary_candidates | tr -d ' '`
-                       message_echo "  $num_leaves_new leaf port(s) is/are newly found; continue for $num_inspect candidate(s)."
-               done
-               grep -E -f "${DBDIR}/grep.leaf_ports.pattern" "${DBDIR}/inspected_ports" | sort -u > ${DBDIR}/leaf_ports || :
-               message_echo
-       }
-       program_exec_and_record_completion INSPECT_REQUIREMENTS_OF_LEAF_PORTS
-fi
-
-# Order the ports considering dependencies
-PROGRAM_DEPENDS='CONVERT_REQUIREMENTS_LIST'
-_program_exec_and_record_completion__operation ()
-{
-       message_section_title "Ordering dependencies"
-       if ! database_build_order_ports_considering_dependencies
-       then
-               message_echo "ERROR: Unsatisfied dependencies are remained:" >&2
-               message_cat "${DBDIR}/unsatisfied.list"
-               message_echo "*** Aborted by ${APPNAME}"
-               message_echo "The ports tree seems broken. You might have caught an incomplete version."
-               message_echo "You are encouraged to update the ports tree by portsnap(8)."
-               message_echo "Then execute"
-               message_echo " ${APPNAME} clean"
-               message_echo "before restart."
-               temp_terminate_process () { :; }
-               exit 1
-       fi
-       message_echo
-}
-program_exec_and_record_completion ORDER_ALL_DEPENDENCIES
-
-# Selection of removing leaf ports
-PROGRAM_DEPENDS='INSPECT_REQUIREMENTS_OF_LEAF_PORTS'
-_program_exec_and_record_completion__operation ()
-{
-       message_section_title "Selection of removing leaf ports"
-       deinstall_select_leaf_ports_to_delete
-       message_echo
-}
-program_exec_and_record_completion SELECT_LEAF_PORTS
-
-# Selection of removing obsolete ports
-PROGRAM_DEPENDS='INSPECT_ALL_DEPENDENCIES PARSE_CONF'
-_program_exec_and_record_completion__operation ()
-{
-       message_section_title "Selection of removing obsolete ports"
-       deinstall_select_obsolete_ports_to_delete
-       message_echo
-}
-program_exec_and_record_completion SELECT_OBSOLETE_PORTS
-
-# Collection of leaf ports to delete
-if [ ! -e "${DBDIR}/inspected_ports_only_partially" ]
-then
-       PROGRAM_DEPENDS='SELECT_LEAF_PORTS'
-       _program_exec_and_record_completion__operation ()
-       {
-               local src src_unselected reqptn_file src_with_initial_origins
-               message_section_title "Collecting leaf ports to delete"
-               src=${DBDIR}/leaf_ports
-               src_unselected=${DBDIR}/leaf_ports_to_delete.unselected
-               src_with_initial_origins=${DBDIR}/leaf_ports.with_ini
-               reqptn_file=${DBDIR}/leaf_ports.requirements_of_unselected.grep_pattern
-               cat "$src_unselected" 2> /dev/null | while read origin
-               do
-                       cat "${DBDIR}/requires/$origin/requirements.all.full" "${DBDIR}/requires/$origin/ignored_requirements.all" || :
-               done 2> /dev/null | sort -u | str_escape_regexp_filter \
-                       | sed 's/^/^/;s/$/$/' > $reqptn_file
-               database_query_add_initial_origins < $src > $src_with_initial_origins
-               message_echo
-       }
-       program_exec_and_record_completion COLLECT_LEAF_PORTS_TO_DELETE
-fi
-
-# Collection of obsolete ports to delete
-PROGRAM_DEPENDS='SELECT_OBSOLETE_PORTS'
-_program_exec_and_record_completion__operation ()
-{
-       local src src_selected src_unselected dst_selected reqptn_file
-       message_section_title "Collecting obsolete ports to delete"
-       src=${DBDIR}/obsolete_ports.can_be_deleted
-       src_selected=${DBDIR}/obsolete_ports_to_delete.selected
-       src_unselected=${DBDIR}/obsolete_ports_to_delete.unselected
-       dst_selected=${DBDIR}/obsolete_ports_to_delete
-       reqptn_file=${DBDIR}/obsolete_ports.requirements_of_unselected.grep_pattern
-       cat "$src_unselected" 2> /dev/null | while read origin
-       do
-               cat "${DBDIR}/initial/$origin/requirements.run.full" || :
-               cat "${DBDIR}/obsolete/$origin/requirements.run.full" || :
-       done | sort -u | str_escape_regexp_filter \
-               | sed 's/^/^/;s/$/$/' > $reqptn_file
-       grep -v -E -f "$reqptn_file" "$src_selected" > $dst_selected 2> /dev/null || :
-       message_echo
-}
-program_exec_and_record_completion COLLECT_OBSOLETE_PORTS_TO_DELETE
-
-# Set up the list of ports to reinstall
-PROGRAM_DEPENDS='ORDER_ALL_DEPENDENCIES'
-_program_exec_and_record_completion__operation ()
-{
-       message_section_title "Setting up the list of ports to reinstall"
-       cp -p "${DBDIR}/reinst_order.list" "${DBDIR}/stage.loop_list/reinst_todo"
-       message_echo
-}
-program_exec_and_record_completion SETUP_REINST_TODO
-
-# Composition of a list for deinstallation of obsolete and leaf packages
-PROGRAM_DEPENDS='COLLECT_LEAF_PORTS_TO_DELETE COLLECT_OBSOLETE_PORTS_TO_DELETE'
-_program_exec_and_record_completion__operation ()
-{
-       local reqptn_leaf reqptn_obs leaf_selected leaf_selected_src obs_selected obs_selected_src grepptn preserved
-       message_section_title "Composing a list for deinstallation of obsolete and leaf packages"
-       reqptn_leaf=${DBDIR}/leaf_ports.requirements_of_unselected.grep_pattern
-       reqptn_obs=${DBDIR}/obsolete_ports.requirements_of_unselected.grep_pattern
-       leaf_selected_src=${DBDIR}/leaf_ports_to_delete.selected
-       leaf_selected=${DBDIR}/leaf_ports_to_delete
-       obs_selected_src=${DBDIR}/obsolete_ports_to_delete.selected
-       obs_selected=${DBDIR}/obsolete_ports_to_delete
-       grepptn=${DBDIR}/ports_to_delete.grep_pattern
-       grepptn_col1=${DBDIR}/ports_to_delete.grep_pattern_col1
-       preserved=${TMPDIR}/LIST_DEINST_PKGS::preserved
-       if [ ! -e "${DBDIR}/inspected_ports_only_partially" ]
-       then
-               cat "$reqptn_leaf" "$reqptn_obs" 2> /dev/null | sort -u > $grepptn
-               grep -v -E -f "$grepptn" "$leaf_selected_src" 2> /dev/null \
-                       | database_query_add_initial_origins > $leaf_selected || :
-               cat "$obs_selected" "$leaf_selected" 2> /dev/null || :
-       else
-               rm -f "$leaf_selected"
-               cat "$obs_selected" 2> /dev/null
-       fi | sort -u > ${DBDIR}/stage.loop_list/ports_to_delete
-       str_escape_regexp_filter < ${DBDIR}/stage.loop_list/ports_to_delete \
-               | sed 's/^/^/;s/$/$/' > $grepptn
-       str_escape_regexp_filter < ${DBDIR}/stage.loop_list/ports_to_delete \
-               | sed 's/^/^/;s/$/[[:space:]]/' > $grepptn_col1
-       cat "${DBDIR}/leaf_ports.with_ini" "${DBDIR}/obsolete_ports" 2> /dev/null \
-               | grep -E -v -f "$grepptn" > ${DBDIR}/stage.loop_list/ports_to_restore || :
-       if [ $opt_batch_mode = no ]
-       then
-               if [ ! -e "${DBDIR}/inspected_ports_only_partially" ] && \
-                       grep -v -E -f "$grepptn" "$leaf_selected_src" > $preserved 2> /dev/null
-               then
-                       message_echo "INFO: Following leaf ports are preserved because required by other preserved leaf/obsolete ports."
-                       message_echo "----------------"
-                       while read origin
-                       do
-                               pkgtag=`cat "${DBDIR}/required/$origin/pkgtag" 2> /dev/null` || :
-                               if [ -n "$pkgtag" ]
-                               then
-                                       echo "$origin" "($pkgtag)"
-                               else
-                                       echo "$origin"
-                               fi
-                       done < $preserved
-                       message_echo "----------------"
-               fi
-               if grep -v -E -f "$grepptn" "$obs_selected_src" > $preserved 2> /dev/null
-               then
-                       message_echo "INFO: Following obsolete ports are preserved because required by other obsolete ports."
-                       message_echo "----------------"
-                       while read origin
-                       do
-                               pkgtag=`cat "${DBDIR}/initial/$origin/installed_version" 2> /dev/null` || :
-                               if [ -n "$pkgtag" ]
-                               then
-                                       echo "$origin" "($pkgtag)"
-                               else
-                                       echo "$origin"
-                               fi
-                       done < $preserved
-                       message_echo "----------------"
-               fi
-       fi
-       message_echo
-}
-program_exec_and_record_completion LIST_DEINST_PKGS
-
-# Collect entire distfiles list
-if [ $opt_inspect_entire_distinfo = yes ]
-then
-       PROGRAM_DEPENDS=''
-       _program_exec_and_record_completion__operation ()
-       {
-               message_section_title "Collecting entire distfiles list"
-               find "${PORTSDIR}" -depth 3 -name distinfo -exec cat {} \; \
-                       | grep '^SHA256 ' | sed -E 's/^SHA256 \(([^)]*)\).*/\1/' \
-                       | sort -u > ${DBDIR}/distfiles.entire.tmp
-               mv "${DBDIR}/distfiles.entire.tmp" "${DBDIR}/distfiles.entire"
-               message_echo
-       }
-       program_exec_and_record_completion COLLECT_ALL_DISTFILES_LIST
-fi
-
-# Inspection of all required distfiles
-PROGRAM_DEPENDS='INSPECT_ALL_DEPENDENCIES COLLECT_ALL_DISTFILES_LIST'
-_program_exec_and_record_completion__operation ()
-{
-       message_section_title "Summarizing distfiles list"
-       cat "${DBDIR}/distfiles.entire" "${DBDIR}/distfiles.inspected" 2> /dev/null \
-               | sort -u | str_escape_regexp_filter \
-               | sed 's|^|^\\.\\/|; s|$|$|' > ${DBDIR}/distfiles.grep.pattern || :
-       message_echo
-}
-program_exec_and_record_completion DISTFILES_LIST
-
-# Clean up of reinstallation status for preparation
-PROGRAM_DEPENDS='REDO_INIT INSPECT_ALL_DEPENDENCIES'
-_program_exec_and_record_completion__operation ()
-{
-       message_section_title "Cleaning up of reinstallation status for preparation"
-       rm -rf "${DBDIR}/status.ports"
-       message_echo
-}
-program_exec_and_record_completion CLEANUP_REINST_STATUS
-
-# Completion of building the temporary database
-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 MAKE_IGNORED_DEPENDENTS_LISTS_UNIQUE COLLECT_LEAF_PORTS_TO_DELETE'
-_program_exec_and_record_completion__operation ()
-{
-       message_section_title "The temporary database is completely built up"
-       message_echo
-}
-program_exec_and_record_completion PREPARATION
+# Execute command operations which must be done before the database construction
+command_all_exec_before_build_database "$@"
 
+# Execute command operations of database construction
+command_all_exec_build_database "$@"
 
 # ==================================================
 # ====================== MAIN ======================
 # ==================================================
 
-# Execute command operations which must be done before actual (re/de)installation processes
-command_exec_before_actual_re_de_installation "$@"
-
-# Set termination messages
-temp_terminate_process ()
-{
-       temp_terminate_process_common
-}
-
-# Reinstallation of remained ports
-PROGRAM_DEPENDS='PREPARATION'
-_program_exec_restartable_loop_operation__routine ()
-{
-       reinstall_exec "$@"
-}
-_program_exec_and_record_completion__operation ()
-{
-       local _MSG_CURRENT_STAGE_general
-       _MSG_CURRENT_STAGE_general="reinstallation"
-       temp_set_msg_current_stage "${_MSG_CURRENT_STAGE_general}"
-       message_section_title "Reinstallation"
-       program_exec_restartable_loop_operation reinst_todo
-       reinstall_restore_conflicts
-       temp_set_msg_current_stage
-       message_echo
-}
-program_exec_and_record_completion REINSTALLATION
-
-# Restoration of obsolete and leaf packages which have been deinstalled but unselected from the deletion list again 
-PROGRAM_DEPENDS='REDO_INIT LIST_DEINST_PKGS'
-_program_exec_restartable_loop_operation__routine ()
-{
-       deinstall_restore "$@"
-}
-_program_exec_and_record_completion__operation ()
-{
-       local _MSG_CURRENT_STAGE_general
-       _MSG_CURRENT_STAGE_general="restoration of unselected obsolete/leaf packages"
-       temp_set_msg_current_stage "${_MSG_CURRENT_STAGE_general}"
-       message_section_title "Restoration of unselected obsolete/leaf packages"
-       program_exec_restartable_loop_operation ports_to_restore
-       temp_set_msg_current_stage
-       message_echo
-}
-program_exec_and_record_completion RESTORE_ONCE_DEINST_PKGS
-
-# Deinstallation of unused obsolete and leaf packages
-PROGRAM_DEPENDS='REDO_INIT LIST_DEINST_PKGS'
-_program_exec_restartable_loop_operation__routine ()
-{
-       deinstall_exec "$@"
-}
-_program_exec_and_record_completion__operation ()
-{
-       local _MSG_CURRENT_STAGE_general
-       _MSG_CURRENT_STAGE_general="deinstallation of obsolete/leaf packages"
-       temp_set_msg_current_stage "${_MSG_CURRENT_STAGE_general}"
-       message_section_title "Deinstallation of unused obsolete/leaf packages"
-       program_exec_restartable_loop_operation ports_to_delete
-       temp_set_msg_current_stage
-       message_echo
-}
-program_exec_and_record_completion DEINST_UNUSED_PKGS
-
-# Clean up obsolete or unused distfiles
-if [ $opt_only_target_scope = no -a $opt_keep_distfiles = no ]
-then
-       PROGRAM_DEPENDS='REINSTALLATION DISTFILES_LIST'
-       _program_exec_and_record_completion__operation ()
-       {
-               local tmp_distfiles_exists
-               message_section_title "Cleaning up obsolete or unused distfiles"
-               tmp_distfiles_exists=${TMPDIR}/CLEANUP_OBSLETE_DISTFILES::distfiles_exists
-               [ $opt_dry_run = yes ] && message_echo "INFO: The operations are not actually carried out."
-               ( set -e; cd "${DISTDIR}" && find . -type f ) \
-                       | sed 's|^\./||' | sort -u > $tmp_distfiles_exists
-               fileedit_manipulate_old_lines "$tmp_distfiles_exists" "${DBDIR}/distfiles.entire" \
-                       | while read distfile
-               do
-                       if [ $opt_batch_mode = no ]
-                       then
-                               echo "  $distfile"
-                       fi
-                       [ $opt_dry_run = yes ] && continue
-                       rm -f "${DISTDIR}/$distfile"
-               done
-               message_echo
-       }
-       program_exec_and_record_completion CLEANUP_OBSLETE_DISTFILES
-fi
-
-# Rebuild of package database
-PROGRAM_DEPENDS='REINSTALLATION RESTORE_ONCE_DEINST_PKGS DEINST_UNUSED_PKGS'
-_program_exec_and_record_completion__operation ()
-{
-       which -s pkgdb || return 0
-       message_section_title "Rebuilding package database for portupgrade"
-       pkgdb -fu
-       message_echo
-}
-program_exec_and_record_completion REBUILD_PKGDB
-
-
-# ==================================================
-# ================ ENDING MESSAGES =================
-# ==================================================
-
-# Notice of failures
-exists_unresolved_ports=
-message_summary_dependents_of_failed_reinstallation failure || exists_unresolved_ports=y
-message_summary_dependents_of_failed_reinstallation redo || exists_unresolved_ports=y
-message_summary_dependents_of_failed_reinstallation conflict || exists_unresolved_ports=y
-[ -n "$exists_unresolved_ports" ] && message_summary_advice_on_manual_solution
-
-# End
-temp_terminate_process () { :; }
+# Execute command operations which must be done before the main process
+command_all_exec_before_main "$@"
 
-if [ -z "$exists_unresolved_ports" ]
-then
-       message_section_title "COMPLETELY DONE"
-       message_echo "- E N D -"
-else
-       message_warn_no_achieved_progress || :
-       message_section_title "Done with some unresolved problems"
-       message_echo "- To be continued -"
-fi
+# Execute command operations as the main process
+command_all_exec_main "$@"
diff --git a/bin/portsreinstall-chroot b/bin/portsreinstall-chroot
new file mode 100755 (executable)
index 0000000..02f8117
--- /dev/null
@@ -0,0 +1,89 @@
+#!/bin/sh -e
+# ==================================================================================
+# portsreinstall chroot main script
+# Copyright (C) 2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# This software is distributed under the 2-Clause BSD License.
+# ==================================================================================
+
+# ==================================================
+# ================== ENVIRONMENT ===================
+# ==================================================
+
+# ============ Set up of environment =============
+PROGRAM=portsreinstall
+APPNAME=`basename "$0"`
+
+MYPREFIX=`realpath "\`dirname \"$0\"\`"/..`
+LIBDIR=${MYPREFIX}/lib/${PROGRAM}
+LIBEXECDIR=${MYPREFIX}/libexec/${PROGRAM}
+SHAREDIR=${MYPREFIX}/share/${PROGRAM}
+ETCDIR=${MYPREFIX}/etc
+
+. ${LIBDIR}/libcommand.sh
+. ${LIBDIR}/libcommand_do.sh
+. ${LIBDIR}/libcommand_flexconf.sh
+. ${LIBDIR}/libcommand_forget.sh
+. ${LIBDIR}/libcommand_pkgs.sh
+. ${LIBDIR}/libcommand_show.sh
+. ${LIBDIR}/libconf.sh
+. ${LIBDIR}/libdatabase_build.sh
+. ${LIBDIR}/libdatabase_maintain.sh
+. ${LIBDIR}/libdatabase_query.sh
+. ${LIBDIR}/libdatabase_record.sh
+. ${LIBDIR}/libdeinstall.sh
+. ${LIBDIR}/libfileedit.sh
+. ${LIBDIR}/libmain.sh
+. ${LIBDIR}/libmessage.sh
+. ${LIBDIR}/libmisc.sh
+. ${LIBDIR}/liboptions.sh
+. ${LIBDIR}/libpkgsys.sh
+. ${LIBDIR}/libprogram.sh
+. ${LIBDIR}/libreinstall.sh
+. ${LIBDIR}/libstr.sh
+. ${LIBDIR}/libtemp.sh
+. ${LIBDIR}/libusage.sh
+
+. ${LIBDIR}/chroot/libcommand.sh
+. ${LIBDIR}/chroot/libcommand_do.sh
+. ${LIBDIR}/chroot/libdatabase_maintain.sh
+. ${LIBDIR}/chroot/libfs.sh
+. ${LIBDIR}/chroot/libmain.sh
+. ${LIBDIR}/chroot/libmessage.sh
+. ${LIBDIR}/chroot/liboptions.sh
+. ${LIBDIR}/chroot/libusage.sh
+
+DBDIR_PROG=/var/tmp/${PROGRAM}.db
+DBDIR=/var/tmp/${APPNAME}.db
+CONFFILE=${ETCDIR}/${PROGRAM}.conf
+PKGTOOLSCONF=${ETCDIR}/pkgtools.conf
+
+main_set_version
+misc_init_vardefs
+temp_trap_init
+
+# ==================================================
+# ========= PARSING OPTIONS AND ARGUMENTS ==========
+# ==================================================
+
+main_parse_options_arguments "$@"
+
+fs_safeguard_basedir "$opt_basedir"
+
+# ========================================================
+# ================== SET UP OF PARAMETERS ==================
+# ========================================================
+main_setup_parameters "$@"
+
+misc_inspect_fs_privilege
+
+main_operation_without_pkg_management_tools "$@"
+
+# ==================================================
+# ====================== MAIN =======================
+# ==================================================
+
+# Execute command operations which must be done before the main process
+command_all_exec_before_main "$@"
+
+# Execute command operations as the main process
+command_all_exec_main "$@"
index 77eba4b..a964a5b 100644 (file)
@@ -1,9 +1,9 @@
 # =======================================================================
 # Configurations for portsreinstall
-# Format version 1.1.0 (Mon May 27 21:58:12 JST 2013)
-#   Comments updated at Mon May 27 21:58:12 JST 2013.
+# Format version 1.2.0 (Wed Jun 25 16:00:40 PHT 2018)
+#   Comments updated at Wed Jun 25 16:00:40 PHT 2018.
 #   Default settings updated at Mon May 27 21:58:12 JST 2013.
-# Copyright (C) 2010-2014 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# Copyright (C) 2010-2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
 # =======================================================================
 
 #  This file is loaded as an include file for Bourne Shell.
 # you use portupgrade(1).
 #  In the all sections, ${id} denotes an arbitrary ID for distinction
 # between the settings in the same section. IDs for imported variables
-# from pkgtools.conf are reserved to match a regular expression
+# from pkgtools.conf are reserved to match an extended regular expression
 # "^pkgtoolsconf_[0-9]+_$".
 #  The all defined variables are applied in the order of their character codes.
 # For duplicated definitions for the same variable are defined, the final one is
-# applied.
+# applied. Regular expression patterns found in this file are processed as
+# extended regular expressions.
 #  When you change these configurations and want to reflect them in a
 # following "redo" process, you must set "-L" option.
 
+# Glob patterns without at sign (@) match all available flavors if defined. See
+# GLOB PATTERNS Section of the man page of portsreinstall(8).
 
 # Alternative environment variable values.
 # SYNTAX: ENV_${envname}=${value}
@@ -84,7 +87,7 @@
 #       HOLD_aaa=autoconf-\*
 #       HOLD_100a=lang/perl\*
 # DESCRIPTION:
-#        Original packages whose port origins are nonexistent MUST be
+#        Original packages whose flavored port origins are nonexistent MUST be
 #       specified here. Obsolete packages which you wish to preserve also
 #       MUST be specified here. Packages listed here are always untouched.
 #       Dependencies and dependents of the specified packages are processed
@@ -103,13 +106,28 @@ HOLD_bsdpan=bsdpan-\*
 # DESCRIPTION:
 #        Morbid or too expensive ports which crash or confuse the system during
 #       (re)installation of themselves or other ports MUST be specified here.
-#       Packages listed here are untouched if the origin exists, and otherwise
-#       deleted. Dependencies and dependents of the specified packages are
-#       processed as usual. If you wish to preserve any of the specified
+#       Packages listed here are untouched if the flavored origin exists, and
+#       otherwise deleted. Dependencies and dependents of the specified packages
+#       are processed as usual. If you wish to preserve any of the specified
 #       packages, you MUST additionally specify them in the HOLD section.
 # CORRESPONDING pkgtools.conf SECTION: (none)
 
 
+# Packages to freeze
+# SYNTAX: FREEZE_${id}=${glob_pattern}
+# EXAMPLE:
+#       FREEZE_001=nvidia-driver-\*
+#       FREEZE_aaa=autoconf-\*
+#       FREEZE_100a=lang/perl\*
+# DESCRIPTION:
+#        Morbid or too expensive ports which crash or confuse the system during
+#       their build but the package installtion by any available version may be safe.
+#       Packages listed here are not attempted to build but package (re)installation
+#       will be attempted as much as possible. If the specified ports failed to
+#       (re)install by packages, build of their dependents are also suppressed.
+# CORRESPONDING pkgtools.conf SECTION: (similar to USE_PKGS_ONLY)
+
+
 # Ports not to be installed by packages
 # SYNTAX: NOPKG_${id}=${glob_pattern}
 # EXAMPLE:
@@ -158,9 +176,30 @@ HOLD_bsdpan=bsdpan-\*
 #               REPLACE_FROM_gcc4=lang/gcc4[24]
 #               REPLACE_TO_gcc4=lang/gcc46
 #       so as to replace the installed package for lang/gcc44 with lang/gcc46.
+#       Unflavored patterns match the all defined flavors, and flavored ports must
+#       be replaced to explicitly flavored ones. For example, when all flavors of
+#       "devel/py-setuptools" should be replaced to @py35, you should set
+#               REPLACE_FROM_py_setuptools_unflavored=devel/py-setuptools'
+#               REPLACE_TO_py_setuptools_unflavored=devel/py-setuptools@py35
+#       so that both flavored and unflavored port names will be replaced.
 # CORRESPONDING pkgtools.conf SECTION: ALT_PKGDEP
 
 
+# Conflict in dependency inspection
+# SYNTAX: CONFLICT_TARGET_${id}=${glob_pattern}
+#         CONFLICT_DEF_${id}=${glob_pattern}
+# EXAMPLE:
+#       CONFLICT_TARGET_firefoxi18='firefox-i18n-[0-9]*'
+#       CONFLICT_DEF_firefoxi18='firefox-[0-9]*'
+#       CONFLICT_TARGET_firefoxesri18=www/firefox-esr-i18n
+#       CONFLICT_DEF_firefoxesri18=www/firefox-esr
+# DESCRIPTION:
+#        Packages matching CONFLICT_DEF are temporarily deinstalled
+#       during inspection of dependency for ports matching
+#       CONFLICT_TARGET.
+# CORRESPONDING pkgtools.conf SECTION: (none)
+
+
 # Arguments for make(1)
 # SYNTAX: MARG_TARGET_${id}=${glob_pattern}
 #         MARG_DEF_${id}=${definitions}
@@ -171,7 +210,11 @@ HOLD_bsdpan=bsdpan-\*
 #       MARG_DEF_cups_pstoraster='WITH_CJK=yes'
 # DESCRIPTION:
 #        When executing make(1) for ports matching MARG_TARGET, the arg-
-#       uments given by MARG_DEF of the same ID are apllied.
+#       uments given by MARG_DEF of the same ID are applied. Flavors
+#       should NOT be specified here, and should be specified in the
+#       flavored origin form such as "devel/py-setuptools@py35" at each
+#       place of ${glob_pattern} throughout in this file and command
+#       operations instead.
 # CORRESPONDING pkgtools.conf SECTION: MAKE_ARGS
 
 
@@ -186,7 +229,10 @@ HOLD_bsdpan=bsdpan-\*
 # DESCRIPTION:
 #        When executing make(1) for ports matching MENV_TARGET, the env-
 #       ironment variable values given by MENV_DEF of the same ID are
-#       applied.
+#       applied. Flavors should NOT be specified here, and should be
+#       "devel/py-setuptools@py35" at each specified in the flavored
+#       origin form such as place of ${glob_pattern} throughout in this file and
+#       command operations instead.
 # CORRESPONDING pkgtools.conf SECTION: MAKE_ENV
 
 
diff --git a/lib/chroot-mount/libcommand.sh b/lib/chroot-mount/libcommand.sh
new file mode 100644 (file)
index 0000000..a977c20
--- /dev/null
@@ -0,0 +1,41 @@
+#!/bin/sh -e
+# ==============================================================================
+# portsreinstall library script
+# Overlay onto lib/libcommand.sh for portsreinstall-chroot-mount
+# - Operations of commands as well as check of command line arguments -
+# Copyright (C) 2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# This software is distributed under the 2-Clause BSD License.
+# ==============================================================================
+
+# ============= Check and parse command line arguments =============
+command_all_parse_args ()
+{
+       COMMAND_RESTART="$@"
+       COMMAND_MODE=${1:-mount}
+       shift || :
+       case $COMMAND_MODE in
+       mount | unmount )
+               _command_parse_args__chk_no_arg $#
+               ;;
+       *)
+               message_echo "ERROR: Invalid command [$COMMAND_MODE]." >&2
+               exit 1
+               ;;
+       esac
+}
+
+# ============= Execute command operations which do not need package tools =============
+command_all_exec_without_pkgtools ()
+{
+       shift || :
+       case $COMMAND_MODE in
+       mount )
+               fs_mount "${SYSTEMBASE}"
+               exit
+               ;;
+       unmount )
+               fs_unmount "${SYSTEMBASE}"
+               exit
+               ;;
+       esac
+}
diff --git a/lib/chroot-mount/libconf.sh b/lib/chroot-mount/libconf.sh
new file mode 100644 (file)
index 0000000..8b53cc5
--- /dev/null
@@ -0,0 +1,18 @@
+#!/bin/sh -e
+# ==============================================================================
+# portsreinstall library script
+# Overlay onto lib/libconf.sh for portsreinstall-chroot-mount
+# - Parsing of configuration files -
+# Copyright (C) 2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# This software is distributed under the 2-Clause BSD License.
+# ==============================================================================
+
+# ============= Set up environment variables =============
+conf_setup_ports_envs ()
+{
+}
+
+# ============= Set up environment variables =============
+conf_setup_packages_envs ()
+{
+}
diff --git a/lib/chroot-mount/libdatabase_maintain.sh b/lib/chroot-mount/libdatabase_maintain.sh
new file mode 100644 (file)
index 0000000..ff4449d
--- /dev/null
@@ -0,0 +1,13 @@
+#!/bin/sh -e
+# ==============================================================================
+# portsreinstall library script
+# Overlay onto lib/libdatabase_maintain.sh for portsreinstall-chroot-mount
+# - Operations for maintaining the temporary database -
+# Copyright (C) 2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# This software is distributed under the 2-Clause BSD License.
+# ==============================================================================
+
+# ============= Creation =============
+database_maintain_create ()
+{
+}
diff --git a/lib/chroot-mount/libmain.sh b/lib/chroot-mount/libmain.sh
new file mode 100644 (file)
index 0000000..926b3ca
--- /dev/null
@@ -0,0 +1,46 @@
+#!/bin/sh -e
+# ==============================================================================
+# portsreinstall library script
+# Overlay onto lib/libmain.sh for portsreinstall-chroot-mount
+# - Common functions of main programs -
+# Copyright (C) 2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# This software is distributed under the 2-Clause BSD License.
+# ==============================================================================
+
+# ============= Set termination messages for special commands =============
+main_set_termination_messages_special ()
+{
+}
+
+# ============= Save the previous configuration if exists =============
+main_save_prev_conf ()
+{
+}
+
+# ============= Load the saved configuration =============
+main_load_conf ()
+{
+       . "${DBDIR}/saved_options.sh"
+       . "${DBDIR}/conf/setenv.sh"
+}
+
+# ============= Get complete configuration variable definitions by importing pkgtools.conf(5) if available =============
+main_get_complete_conf ()
+{
+}
+
+# ============= Parse the configuration =============
+main_parse_conf ()
+{
+}
+
+# ============= Check of the mounting/unmounting privilege of the environment =============
+main_check_of_mounting_unmounting_privilege ()
+{
+       if ! misc_chk_mount_privilege || ! misc_chk_unmount_privilege
+       then
+               temp_terminate_process () { :; }
+               message_echo "ERROR: The current environment does not have the full privilege to mount and unmount file systems." >&2
+               exit 1
+       fi
+}
diff --git a/lib/chroot-mount/libmessage.sh b/lib/chroot-mount/libmessage.sh
new file mode 100644 (file)
index 0000000..9839e36
--- /dev/null
@@ -0,0 +1,19 @@
+#!/bin/sh -e
+# ==============================================================================
+# portsreinstall library script
+# Overlay onto lib/libmessage.sh for portsreinstall-chroot-mount
+# - Messages -
+# Copyright (C) 2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# This software is distributed under the 2-Clause BSD License.
+# ==============================================================================
+
+# ============= Output the brief description =============
+message_brief_description ()
+{
+       cat << eof
+ -- Utility to mount and unmount file systems for portsreinstall-chroot,
+ -- Which is a part of portsreinstall,
+ -- The ports upgrading utility for massive forced reinstallation
+ -- And for those who are pursuing the perfect packages environment
+eof
+}
diff --git a/lib/chroot-mount/liboptions.sh b/lib/chroot-mount/liboptions.sh
new file mode 100644 (file)
index 0000000..467fed1
--- /dev/null
@@ -0,0 +1,23 @@
+#!/bin/sh -e
+# ==============================================================================
+# portsreinstall library script
+# Overlay onto lib/liboptions.sh for portsreinstall-chroot-mount
+# - Command line options -
+# Copyright (C) 2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# This software is distributed under the 2-Clause BSD License.
+# ==============================================================================
+
+# ============= Database of options which are given at each run and not saved =============
+# [Syntax of option databases]
+# short_name, long_name, variable, defult_vaule, set_value
+# Columns are delimited by tab characters.
+options_db_onetime ()
+{
+       cat << eof
+h      help    opt_help_mode   0       1
+h      short-help      opt_help_mode   0       1
+V      show-version    opt_show_version        no      yes
+a      batch-mode      opt_batch_mode  no      yes
+S      no-opening-message      opt_no_opening_message  no      yes
+eof
+}
diff --git a/lib/chroot-mount/libtemp.sh b/lib/chroot-mount/libtemp.sh
new file mode 100644 (file)
index 0000000..b964333
--- /dev/null
@@ -0,0 +1,30 @@
+#!/bin/sh -e
+# ==============================================================================
+# portsreinstall library script
+# Overlay onto lib/libtemp.sh for portsreinstall-chroot-mount
+# - Temporary directory and signal trapping -
+# Copyright (C) 2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# This software is distributed under the 2-Clause BSD License.
+# ==============================================================================
+
+# ============= Set the termination process =============
+temp_setup_terminate_process ()
+{
+       temp_terminate_process ()
+       {
+               local errno
+               errno=${1:-0}
+               [ $opt_batch_mode = yes -o $errno -eq 0 ] && return
+               message_echo
+               if [ $errno -eq 130 ]
+               then
+                       message_echo "INFO: Terminated at `message_timestamp`."
+                       message_echo
+                       message_echo " You can safely rerun to continue."
+               else
+                       message_echo "INFO: Aborted at `message_timestamp`."
+                       message_echo
+                       message_echo " You may rerun to continue after manually resolving the problem."
+               fi
+       }
+}
diff --git a/lib/chroot-mount/libusage.sh b/lib/chroot-mount/libusage.sh
new file mode 100644 (file)
index 0000000..d4b3c0e
--- /dev/null
@@ -0,0 +1,36 @@
+#!/bin/sh -e
+# ==============================================================================
+# portsreinstall library script
+# Overlay onto lib/libusage.sh for portsreinstall-chroot-mount
+# - Help messages -
+# Copyright (C) 2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# This software is distributed under the 2-Clause BSD License.
+# ==============================================================================
+
+# ============= Content of the short help =============
+usage_short_content ()
+{
+       cat << eof
+USAGE: ${APPNAME} [OPTIONS] [--] [command]
+
+[OPTIONS]
+ <Group 1: Just show messages and exit without operation>
+ -H : Show a long help whose content is the same as the manual page.
+ -h : Show this short help.
+ -V : Show the current version.
+ <Group 2: Effective anytime>
+ -a : Suppress messages to be batch-friendly.
+ -S : Suppress the credit and opening messages.
+
+[ARGUMENTS]
+ command:
+            mount (default)  | unmount
+
+[DESCRIPTIONS]
+ This utility is for assisting portsreinstall-chroot(8) to mount and unmount a builder environment at the grand host environment in case that the target environment is a chroot(8) or jail(8) virtual environment which does not have sufficient privilege to operate the file systems. Execution of this utility will be suggested by portsreinstall-chroot(8) executed at the target environment. The executable file of this utility is installed outside the scope of the search paths, and expected to be launched by specifying the full path.
+
+
+[ROBUSTNESS AGAINST TERMINATION AND RESTART]
+ Execution of this utility can be terminated at any points and restarted from there.
+eof
+}
diff --git a/lib/chroot/libcommand.sh b/lib/chroot/libcommand.sh
new file mode 100644 (file)
index 0000000..884907b
--- /dev/null
@@ -0,0 +1,126 @@
+#!/bin/sh -e
+# ==============================================================================
+# portsreinstall library script
+# Overlay onto lib/libcommand.sh for portsreinstall-chroot
+# - Operations of commands as well as check of command line arguments -
+# Copyright (C) 2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# This software is distributed under the 2-Clause BSD License.
+# ==============================================================================
+
+# ============= Check the necessity of opening notice =============
+command_all_chk_need_opening_notice ()
+{
+       false
+}
+
+# ============= Execute command operations before getting the temporary database ready =============
+command_all_exec_before_db_creation ()
+{
+       local COMMAND_RESTART COMMAND_MODE COMMAND_OPERATION
+       COMMAND_RESTART="$@"
+       COMMAND_MODE=${1:-do}
+       shift || :
+       case $COMMAND_MODE in
+       clean )
+               COMMAND_OPERATION=${1:-normal}
+               shift || :
+               _command_parse_args__chk_no_arg $#
+               case $COMMAND_OPERATION in
+               force )
+                       database_clean_destroy_force
+                       exit
+                       ;;
+               esac
+               ;;
+       esac
+}
+
+# ============= Check and parse command line arguments =============
+command_all_parse_args ()
+{
+       local num_args_init
+       num_args_init=$#
+       COMMAND_RESTART="$@"
+       COMMAND_MODE=${1:-do}
+       shift || :
+       case $COMMAND_MODE in
+       clean )
+               COMMAND_OPERATION=${1:-normal}
+               shift || :
+               case $COMMAND_OPERATION in
+               normal )
+                       misc_chk_privilege
+                       ;;
+               esac
+               _command_parse_args__chk_no_arg $#
+               ;;
+       do | mount | unmount | enter | sync | options )
+               misc_chk_privilege
+               _command_parse_args__chk_no_arg $#
+               ;;
+       *)
+               message_echo "ERROR: Invalid command [$COMMAND_MODE]." >&2
+               exit 1
+               ;;
+       esac
+       COMMAND_SHIFT=$(($num_args_init - $#))
+}
+
+# ============= Execute command operations which should be done without upgrade of tools =============
+command_all_exec_before_tools_upgrade ()
+{
+       case $COMMAND_MODE in
+       clean )
+               database_clean_destroy
+               exit
+               ;;
+       unmount )
+               fs_terminate_if_unmount_unavailable
+               fs_unmount
+               exit
+               ;;
+       mount )
+               command_do_chroot_cleanup
+               fs_build_chroot
+               fs_terminate_if_mount_unavailable
+               fs_mount
+               temp_reset_termination_messages_common
+               message_echo "Done"
+               exit
+               ;;
+       enter )
+               command_do_chroot_cleanup
+               fs_build_chroot
+               fs_terminate_if_mount_unavailable
+               fs_mount
+               command_do_chroot_enter
+               message_echo "Exited successfully"
+               program_deregister_stage_complete UPGRADE_GUEST
+               exit
+               ;;
+       sync )
+               command_do_chroot_cleanup
+               fs_build_chroot
+               fs_terminate_if_mount_unavailable
+               fs_mount
+               command_do_update_host_files
+               message_echo "Done"
+               exit
+               ;;
+       options )
+               options_show_all
+               exit
+               ;;
+       esac
+}
+
+# ============= Execute command operations as the main process =============
+command_all_exec_main ()
+{
+       case $COMMAND_MODE in
+       do)
+               command_do_main
+               command_do_ending_process
+               ;;
+       esac
+}
diff --git a/lib/chroot/libcommand_do.sh b/lib/chroot/libcommand_do.sh
new file mode 100644 (file)
index 0000000..a791a4e
--- /dev/null
@@ -0,0 +1,222 @@
+#!/bin/sh -e
+# ==============================================================================
+# portsreinstall library script
+# Overlay onto lib/libcommand_do.sh for portsreinstall-chroot
+# - "do" command operation -
+# Copyright (C) 2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# This software is distributed under the 2-Clause BSD License.
+# ==============================================================================
+
+# ============= Check the completion of build at the chroot environment =============
+command_do_chk_build_completion ()
+{
+       [ -e "$opt_basedir/builder/${DBDIR_PROG}"/stage.complete/ALL_COMPLETE ]
+}
+
+# ============= Enter the guest =============
+command_do_chroot_enter ()
+{
+       local shellcmd
+       message_cat <<eof
+=========================================================
+You entered the builder chroot environment.
+Complete the update of packages by portsreinstall(8),
+Then exit to the target environment.
+=========================================================
+
+eof
+       shellcmd=`id -P | sed -E 's|.*:([^:]*)$|\1|'`
+       case `basename "$shellcmd"` in
+       sh | ksh | zsh | '' )
+               shellcmd="env PS1='\\\$@[builder]\h\\$ ' ${shellcmd:-/bin/sh}"
+               ;;
+       bash )
+               shellcmd="env PS1='\u@[builder]\h\\$ ' $shellcmd"
+               ;;
+       esac
+       chroot "$opt_basedir"/builder "$shellcmd"
+}
+
+# ============= Update of the files affecting package installation of the host environment  =============
+command_do_update_host_files ()
+{
+       local dirpath filepath
+       message_echo "Updating the files affecting package installation (packages, distfiles, port options, ports/packages management tools configurations) of the host environment..."
+       for dirpath in "${DISTDIR}" "${PACKAGES}" "${PORT_DBDIR}"
+       do
+               (
+                       mkdir -p "$dirpath"
+                       cd $dirpath && find . -type f
+               ) | while read file
+               do
+                       [ -e "$opt_basedir/builder$dirpath/$file" ] || rm "$dirpath/$file"
+               done
+               (
+                       cd "$opt_basedir"/builder$dirpath && find . -type f
+               ) | while read file
+               do
+                       [ ! -e "$dirpath/$file" -o "$opt_basedir/builder$dirpath/$file" -nt "$dirpath/$file" ] || continue
+                       nodedir=`dirname "$dirpath/$file"`
+                       mkdir -p "$nodedir"
+                       cp -p "$opt_basedir/builder$dirpath/$file" "$dirpath/$file"
+               done
+               set +x
+               find -d $dirpath -type d -empty -delete
+       done
+       for filepath in "${LOCALBASE}"/etc/portsreinstall.conf "${LOCALBASE}"/etc/pkgtools.conf "${LOCALBASE}"/etc/pkg.conf /etc/make.conf "${DBDIR}"
+       do
+               if [ -e "$opt_basedir"/builder$filepath ]
+               then
+                       [ ! -e $filepath -o "$opt_basedir"/builder$filepath -nt $filepath ] && cp -p "$opt_basedir"/builder$filepath $filepath
+               else
+                       rm -f $filepath
+               fi
+       done
+       :
+}
+
+# ============= Ending process =============
+command_do_ending_process ()
+{
+       temp_terminate_process () { :; }
+       if [ $opt_no_opening_message = yes ]
+       then
+               message_echo "Done as ${APPNAME}"
+               return
+       fi
+       message_section_title "COMPLETELY DONE"
+       message_echo "- E N D -"
+}
+
+# ============= Initial clean up =============
+command_do_chroot_cleanup  ()
+{
+       local PROGRAM_DEPENDS
+       PROGRAM_DEPENDS=
+       _program_exec_and_record_completion__operation ()
+       {
+               fs_destroy
+       }
+       program_exec_and_record_completion CLEANUP_GUEST
+}
+
+# ============= Enter the chroot environment =============
+command_do_chroot_enter_if_incomplete ()
+{
+       local PROGRAM_DEPENDS
+       command_do_chk_build_completion || program_deregister_stage_complete UPGRADE_GUEST
+       PROGRAM_DEPENDS='CLEANUP_GUEST'
+       _program_exec_and_record_completion__operation ()
+       {
+               message_echo
+               if ! command_do_chroot_enter
+               then
+                       message_echo "INFO: The last exit status in the builder chroot environment was non-zero." >&2
+                       exit 1
+               fi
+               if ! command_do_chk_build_completion
+               then
+                       message_echo "ERROR: Exited from the builder chroot environment without completing the build." >&2
+                       exit 1
+               fi
+               message_echo "INFO: The package build completed."
+               message_echo "Is it OK to apply the upgrade to the host environment? ([y]/n)"
+               if ! message_query_yn_default_yes
+               then
+                       message_echo "INFO: Terminated because the continuation is stopped by the user."
+                       exit 1
+               fi
+       }
+       program_exec_and_record_completion UPGRADE_GUEST
+}
+
+# ============= Pack (re)installed packages at the chroot environment =============
+command_do_chroot_pack_update ()
+{
+       local PROGRAM_DEPENDS
+       if [ -e "$opt_basedir"/store/complete ]
+       then
+               if ! command_do_chk_build_completion
+               then
+                       program_deregister_stage_complete PACK_PKGS
+                       rm -rf "$opt_basedir"/store/complete
+               fi
+       else
+               program_deregister_stage_complete PACK_PKGS
+       fi
+       PROGRAM_DEPENDS='UPGRADE_GUEST'
+       _program_exec_and_record_completion__operation ()
+       {
+               message_echo "Packing the upgrades..."
+               [ $opt_batch_mode = yes ] && opt_quiet='-a '
+               chroot "$opt_basedir"/builder /bin/csh -c "${PROGRAM} -S $opt_quiet packupgrade create && ${PROGRAM} -S $opt_quiet packupgrade crop /.${PROGRAM}"
+       }
+       program_exec_and_record_completion PACK_PKGS
+}
+
+# ============= Update of the files affecting package installation of the host environment  =============
+command_do_chroot_update_host_files ()
+{
+       local PROGRAM_DEPENDS
+       PROGRAM_DEPENDS='PACK_PKGS'
+       _program_exec_and_record_completion__operation ()
+       {
+               command_do_update_host_files
+       }
+       program_exec_and_record_completion UPDATE_HOST
+}
+
+# ============= Update of packages at the host environment =============
+command_do_chroot_update_host_pkgs ()
+{
+       local PROGRAM_DEPENDS
+       PROGRAM_DEPENDS='UPDATE_HOST'
+       _program_exec_and_record_completion__operation ()
+       {
+               message_echo "Extracting the upgrade archive..."
+               (
+                       cd "$opt_basedir"/store
+                       rm -rf work
+                       mkdir work
+                       tar xzf portsreinstall-upgrade.tar.gz -C work
+               )
+       }
+       program_exec_and_record_completion EXTRACT_SCRIPT_ARCHIVE
+       PROGRAM_DEPENDS='EXTRACT_SCRIPT_ARCHIVE'
+       _program_exec_and_record_completion__operation ()
+       {
+               message_echo "Updating the packages at the host environment..."
+               (
+                       cd "$opt_basedir"/store
+                       opt_quiet=
+                       [ $opt_batch_mode = yes ] && opt_quiet='-a '
+                       work/portsreinstall-upgrade -S clean
+                       work/portsreinstall-upgrade -S $opt_quiet -P "${PACKAGES}/${PKGREPOSITORYSUBDIR}"
+               )
+       }
+       program_exec_and_record_completion UPGRADE_HOST
+}
+
+# ============= Main operation of do/redo =============
+command_do_main ()
+{
+       # Initial clean up
+       command_do_chroot_cleanup
+       
+       # Build and mount of the chroot environment
+       fs_build_chroot
+       fs_terminate_if_mount_unavailable
+       fs_mount
+       
+       # Enter the guest
+       command_do_chroot_enter_if_incomplete
+       
+       # Pack (re)installed packages at the guest
+       command_do_chroot_pack_update
+       
+       # Update of the files affecting package installation of the host environment 
+       command_do_chroot_update_host_files
+       
+       # Update of packages at the host environment
+       command_do_chroot_update_host_pkgs
+}
diff --git a/lib/chroot/libdatabase_maintain.sh b/lib/chroot/libdatabase_maintain.sh
new file mode 100644 (file)
index 0000000..770cae3
--- /dev/null
@@ -0,0 +1,28 @@
+#!/bin/sh -e
+# ==============================================================================
+# portsreinstall-chroot library script
+# Overlay onto lib/libdatabase_maintain.sh for portsreinstall-chroot
+# - Operations on the temporary database -
+# Copyright (C) 2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# This software is distributed under the 2-Clause BSD License.
+# ==============================================================================
+
+# ============= Destroy the builder chroot environment and clean up the temporary database =============
+database_clean_destroy ()
+{
+       local systembase
+       systembase=$1
+       message_echo "Starting to clean up the builder chroot environment..."
+       fs_destroy "$systembase"
+       message_echo "Starting to clean up the temporary database..."
+       command_exec_without_pkgtools__notify_reset_options
+       rm -rf "${DBDIR}"
+       message_echo "Done"
+}
+
+# ============= Forcibly destroy the builder chroot environment and clean up the temporary database =============
+database_clean_destroy_force ()
+{
+       [ -e "${DBDIR}/saved_options.sh" ] && . "${DBDIR}/saved_options.sh"
+       database_clean_destroy
+}
diff --git a/lib/chroot/libfs.sh b/lib/chroot/libfs.sh
new file mode 100644 (file)
index 0000000..eb47095
--- /dev/null
@@ -0,0 +1,369 @@
+#!/bin/sh -e
+# ==============================================================================
+# portsreinstall-chroot library script for portsreinstall-chroot
+# - File system operations -
+# Copyright (C) 2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# This software is distributed under the 2-Clause BSD License.
+# ==============================================================================
+
+# ============= Check the safety of the base directory of builder chroot environment =============
+fs_chk_safety_basedir ()
+{
+       local basedir
+       basedir=$1
+       [ -n "$basedir" ] || return
+       case "$basedir" in
+       /|/bin|/boot|/compat|/dev|/entropy|/etc|/home|/host|/lib|/libexec|/net|/proc|/rescue|/root|/sbin|/sys|/tmp|/usr|/var)
+               return 1
+               ;;
+       esac
+       expr "$basedir" : '^/boot/.*' > /dev/null && return 1
+       expr "$basedir" : '^/compat/.*' > /dev/null && return 1
+       expr "$basedir" : '^/dev/.*' > /dev/null && return 1
+       expr "$basedir" : '^/etc/.*' > /dev/null && return 1
+       expr "$basedir" : '^/lib/.*' > /dev/null && return 1
+       expr "$basedir" : '^/libexec/.*' > /dev/null && return 1
+       expr "$basedir" : '^/proc/.*' > /dev/null && return 1
+       expr "$basedir" : '^/sbin/.*' > /dev/null && return 1
+       :
+}
+
+# ============= Safeguard of the base directory of builder chroot environment =============
+fs_safeguard_basedir ()
+{
+       local basedir
+       basedir=$1
+       fs_chk_safety_basedir "$basedir" && return
+       message_echo "ERROR: The base directory [$opt_basedir] is not safe." >&2
+       exit 1
+}
+
+# ============= Build the file systems for the builder chroot environment =============
+fs_build_chroot ()
+{
+       local systembase
+       systembase=$1
+       [ -e "${DBDIR}/mount_manifest" ] && return
+       message_echo "Building the file systems for builder chroot environment (if not yet)."
+       fs_safeguard_basedir "$opt_basedir"
+       fs_unmount "$systembase"
+       mkdir -p "$systembase/$opt_basedir"
+       # Prescan the f file system of the original environment
+       cp /dev/null "${TMPDIR}/fs_build_chroot:directories"
+       (
+               {
+                       echo bin compat etc lib libexec root sbin sys usr var | tr ' ' '\n'
+                       echo "$opt_extra_dirs" | tr "$opt_extra_dirs_delim" '\n'
+               } | grep -v '^[[:space:]]*$' | sort -u > ${TMPDIR}/fs_build_chroot:sys_dirs
+               sysdirs_ptn="^/*(`str_escape_regexp_filter < ${TMPDIR}/fs_build_chroot:sys_dirs | tr '\n' '|' | sed 's/\|$//'`)/+"
+               while read directory
+               do
+                       [ -e "$systembase"/$directory ] || continue
+                       if [ -L "$systembase"/$directory ]
+                       then
+                               src_mountpoint_real=`realpath "$systembase"/$directory`
+                                       printf '%s\t%s\n' link $directory >> ${TMPDIR}/fs_build_chroot:directories
+                               if ! echo "$src_mountpoint_real/" | grep -qE "$sysdirs_ptn"
+                               then
+                                       printf '%s\t%s\n' real "$src_mountpoint_real" >> ${TMPDIR}/fs_build_chroot:directories
+                                       tmpdir_descendant=${TMPDIR}/fs_build_chroot:descendant/$src_mountpoint_real
+                                       mkdir -p "$tmpdir_descendant"
+                                       misc_get_descendant_mount_info "$systembase/$src_mountpoint_real" > $tmpdir_descendant/list
+                               fi
+                       elif [ -d "$systembase"/$directory ]
+                       then
+                               printf '%s\t%s\n' real $directory >> ${TMPDIR}/fs_build_chroot:directories
+                               tmpdir_descendant=${TMPDIR}/fs_build_chroot:descendant/$directory
+                               mkdir -p "$tmpdir_descendant"
+                               misc_get_descendant_mount_info "$systembase/$directory" > $tmpdir_descendant/list
+                       fi
+               done < ${TMPDIR}/fs_build_chroot:sys_dirs
+       )
+       # Prepare the grand base of the chroot environment
+       (
+               cd "$systembase/$opt_basedir"
+               for directory in builder mask store
+               do
+                       [ -d $directory ] || mkdir $directory
+               done
+       )
+       # Build target directories and the manifest for mounting
+       cp /dev/null "${DBDIR}/mount_manifest.tmp"
+       (
+               cd "$systembase/$opt_basedir"/builder
+               while read srcline
+               do
+                       type=`echo "$srcline" | cut -f 1`
+                       directory=`echo "$srcline" | cut -f 2`
+                       case $type in
+                       link )
+                               [ -e "$directory" -o -L "$directory" ] || cp -RpP "$systembase/$directory" .
+                               ;;
+                       real )
+                               mkdir -p "./$directory"
+                               masktarget=$systembase/$opt_basedir/mask/$directory
+                               mkdir -p "$masktarget"
+                               printf '%s\t%s\t%s\t%s\n' nullfs "$systembase"/$directory $directory ro >> ${DBDIR}/mount_manifest.tmp
+                               printf '%s\t%s\t%s\t%s\n' unionfs "$masktarget" $directory noatime >> ${DBDIR}/mount_manifest.tmp
+                               while read srcline
+                               do
+                                       fs=`echo "$srcline" | cut -f 1`
+                                       mp=`echo "$srcline" | cut -f 2`
+                                       relative=`echo "$srcline" | cut -f 3`
+                                       case $fs in
+                                               normal )
+                                                       masktarget=$systembase/$opt_basedir/mask/$directory/$relative
+                                                       mkdir -p "$masktarget"
+                                                       printf '%s\t%s\t%s\t%s\n' nullfs "$mp" "$directory/$relative" ro >> ${DBDIR}/mount_manifest.tmp
+                                                       printf '%s\t%s\t%s\t%s\n' unionfs "$masktarget" "$directory/$relative" noatime >> ${DBDIR}/mount_manifest.tmp
+                                                       ;;
+                                               devfs )
+                                                       printf '%s\t%s\t%s\t%s\n' devfs devfs "$directory/$relative" '' >> ${DBDIR}/mount_manifest.tmp
+                                                       ;;
+                                               fdescfs )
+                                                       printf '%s\t%s\t%s\t%s\n' fdescfs fdesc "$directory/$relative" '' >> ${DBDIR}/mount_manifest.tmp
+                                                       ;;
+                                               procfs )
+                                                       printf '%s\t%s\t%s\t%s\n' procfs proc "$directory/$relative" '' >> ${DBDIR}/mount_manifest.tmp
+                                                       ;;
+                                               linprocfs )
+                                                       printf '%s\t%s\t%s\t%s\n' linprocfs linproc "$directory/$relative" '' >> ${DBDIR}/mount_manifest.tmp
+                                                       ;;
+                                               tmpfs )
+                                                       printf '%s\t%s\t%s\t%s\n' tmpfs tmpfs "$directory/$relative" mode=1777 >> ${DBDIR}/mount_manifest.tmp
+                                                       ;;
+                                       esac
+                               done < ${TMPDIR}/fs_build_chroot:descendant/$directory/list
+                               ;;
+                       esac
+               done < ${TMPDIR}/fs_build_chroot:directories
+               for directory in dev proc tmp 
+               do
+                       [ -e $directory ] || mkdir $directory
+               done
+               printf '%s\t%s\t%s\t%s\n' devfs devfs dev '' >> ${DBDIR}/mount_manifest.tmp
+               printf '%s\t%s\t%s\t%s\n' fdescfs fdesc dev/fd '' >> ${DBDIR}/mount_manifest.tmp
+               printf '%s\t%s\t%s\t%s\n' procfs proc proc '' >> ${DBDIR}/mount_manifest.tmp
+               printf '%s\t%s\t%s\t%s\n' tmpfs tmpfs tmp mode=1777 >> ${DBDIR}/mount_manifest.tmp
+               mkdir -p ."${PROGRAM}"
+               cd "$systembase/$opt_basedir/mask"
+               if [ ! -e root/.cshrc ]
+               then
+                       tmp_cshrc=${TMPDIR}/fs_build_chroot:.cshrc
+                       [ -d root ] || mkdir root
+                       if [ -e "$systembase"/root/.cshrc ]
+                       then
+                               cp -p "$systembase"/root/.cshrc "$tmp_cshrc"
+                               cp -p "$systembase"/root/.cshrc "root/.cshrc.bak-${APPNAME}"
+                       elif [ -e "$systembase"/usr/share/skel/dot.cshrc ]
+                       then
+                               cp -p "$systembase"/usr/share/skel/dot.cshrc "$tmp_cshrc"
+                               touch "root/.cshrc.bak-${APPNAME}"
+                       else
+                               cp /dev/null "$tmp_cshrc"
+                       fi
+                       echo >> $tmp_cshrc
+                       echo 'set prompt="%N@[builder]%m:%~ %# "' >> $tmp_cshrc
+                       mv "$tmp_cshrc" root/.cshrc
+               fi
+               printf '%s\t%s\t%s\t%s\n' nullfs "$systembase/$opt_basedir"/store ".${PROGRAM}" '' >> ${DBDIR}/mount_manifest.tmp
+       )
+       mv "${DBDIR}/mount_manifest.tmp" "${DBDIR}/mount_manifest"
+}
+
+# ============= Check whether the file systems for the builder chroot environment are all mounted =============
+fs_chk_mount ()
+{
+       local systembase
+       systembase=$1
+       [ -e "${DBDIR}/mount_manifest" ] || return
+       rm -rf ${TMPDIR}/fs_chk_mount:remains
+       while read srcline
+       do
+               type=`echo "$srcline" | cut -f 1`
+               target=`echo "$srcline" | cut -f 2`
+               [ "x$type" = xnullfs -o "x$type" = xunionfs ] && target=$systembase/$target
+               directory=`echo "$srcline" | cut -f 3`
+               opt=`echo "$srcline" | cut -f 4`
+               if ! misc_chk_mounted "$type" "$target" "$systembase/$opt_basedir/builder/$directory"
+               then
+                       touch "${TMPDIR}"/fs_chk_mount:remains
+                       break
+               fi
+       done < ${DBDIR}/mount_manifest
+       [ ! -e "${TMPDIR}"/fs_chk_mount:remains ]
+}
+
+# ============= Terminate when the file systems for the builder chroot environment cannot be mounted =============
+fs_terminate_if_mount_unavailable ()
+{
+       local systembase
+       systembase=$1
+       fs_chk_mount "$systembase" && return
+       misc_chk_mount_privilege && return
+       temp_terminate_process ()
+       {
+               local errno basedir
+               errno=${1:-0}
+               [ $opt_batch_mode = yes ] && return
+               if [ $errno -ne 2 ]
+               then
+                       message_echo "Aborted by unexpected error" >&2
+                       exit
+               fi
+               message_echo
+               message_echo "INFO: Terminated for mounting file systems because this utility was executed at a virtual (chroot or jail) environment."
+               message_echo "Execute"
+               basedir=`misc_get_system_basedir`
+               if [ -n "$basedir" ]
+               then
+                       message_echo "  $basedir${SHAREDIR}/bin/portsreinstall-chroot-mount"
+                       message_echo "at the grand host environment."
+               else
+                       message_echo "  \$BASEDIR${SHAREDIR}/bin/portsreinstall-chroot-mount"
+                       message_echo "at the grand host environment, where \$BASEDIR denotes the base directory of this virtual environment."
+               fi
+               message_echo "After its successful execution, rerun"
+               if [ -n "$COMMAND_RESTART" ]
+               then
+                       message_echo "  ${APPNAME} $COMMAND_RESTART"
+               else
+                       message_echo "  ${APPNAME}"
+               fi
+       }
+       exit 2
+}
+
+# ============= Mount the file systems for the builder chroot environment if not yet =============
+fs_mount ()
+{
+       local systembase
+       systembase=$1
+       message_echo "Mounting the file systems for builder chroot environment."
+       fs_safeguard_basedir "$opt_basedir"
+       while read srcline
+       do
+               type=`echo "$srcline" | cut -f 1`
+               target=`echo "$srcline" | cut -f 2`
+               [ "x$type" = xnullfs -o "x$type" = xunionfs ] && target=$systembase/$target
+               directory=`echo "$srcline" | cut -f 3`
+               opt=`echo "$srcline" | cut -f 4`
+               mp=$systembase/$opt_basedir/builder/$directory
+               if ! misc_chk_mounted "$type" "$target" "$mp"
+               then
+                       mount -t "$type" -o "$opt" "$target" "$mp"
+               fi
+       done < ${DBDIR}/mount_manifest
+       if ! fs_chk_mount "$systembase"
+       then
+               message_echo "Error: Failed to mount the file systems. Some of them remain unmounted." >&2
+               exit 1
+       fi
+       message_echo "Mounting done."
+}
+
+# ============= Check whether the file systems for the builder chroot environment are all unmounted or destroyed =============
+fs_chk_unmount ()
+{
+       local systembase
+       systembase=$1
+       [ -e "${DBDIR}/mount_manifest" ] || return 0
+       rm -rf ${TMPDIR}/fs_chk_unmount:remains
+       tail -r "${DBDIR}/mount_manifest" | while read srcline
+       do
+               type=`echo "$srcline" | cut -f 1`
+               target=`echo "$srcline" | cut -f 2`
+               [ "x$type" = xnullfs -o "x$type" = xunionfs ] && target=$systembase/$target
+               directory=`echo "$srcline" | cut -f 3`
+               opt=`echo "$srcline" | cut -f 4`
+               if misc_chk_mounted "$type" "$target" "$systembase/$opt_basedir/builder/$directory"
+               then
+                       touch "${TMPDIR}"/fs_chk_unmount:remains
+                       break
+               fi
+       done
+       [ ! -e "${TMPDIR}"/fs_chk_unmount:remains ]
+}
+
+# ============= Terminate when the file systems for the builder chroot environment cannot be unmounted =============
+fs_terminate_if_unmount_unavailable ()
+{
+       local systembase
+       systembase=$1
+       fs_chk_unmount "$systembase" && return
+       misc_chk_unmount_privilege && return
+       temp_terminate_process ()
+       {
+               local errno basedir
+               errno=${1:-0}
+               [ $opt_batch_mode = yes ] && return
+               if [ $errno -ne 3 ]
+               then
+                       message_echo "Aborted by unexpected error" >&2
+                       exit
+               fi
+               message_echo
+               message_echo "INFO: Terminated for unmounting file systems because this utility was executed at a virtual (chroot or jail) environment."
+               message_echo "Execute"
+               basedir=`misc_get_system_basedir`
+               if [ -n "$basedir" ]
+               then
+                       message_echo "  $basedir${SHAREDIR}/bin/portsreinstall-chroot-mount unmount"
+                       message_echo "at the grand host environment."
+               else
+                       message_echo "  \$BASEDIR${SHAREDIR}/bin/portsreinstall-chroot-mount unmount"
+                       message_echo "at the grand host environment, where \$BASEDIR denotes the base directory of this virtual environment."
+               fi
+               message_echo "After its successful execution, rerun"
+               if [ -n "$COMMAND_RESTART" ]
+               then
+                       message_echo "  ${APPNAME} $COMMAND_RESTART"
+               else
+                       message_echo "  ${APPNAME}"
+               fi
+       }
+       exit 3
+}
+
+# ============= Unmount  file systems for the chroot environment =============
+fs_unmount ()
+{
+       local systembase
+       systembase=$1
+       [ ! -d "$systembase/$opt_basedir"/builder ] && return
+       [ -e "${DBDIR}/mount_manifest" ] || return 0
+       message_echo "Unmounting the file systems for builder chroot."
+       fs_safeguard_basedir "$opt_basedir"
+       tail -r "${DBDIR}/mount_manifest" | while read srcline
+       do
+               type=`echo "$srcline" | cut -f 1`
+               target=`echo "$srcline" | cut -f 2`
+               [ "x$type" = xnullfs -o "x$type" = xunionfs ] && target=$systembase/$target
+               directory=`echo "$srcline" | cut -f 3`
+               opt=`echo "$srcline" | cut -f 4`
+               mp=$systembase/$opt_basedir/builder/$directory
+               if misc_chk_mounted "$type" "$target" "$mp"
+               then
+                       umount -f "$mp"
+               fi
+       done
+       if ! fs_chk_unmount "$systembase"
+       then
+               message_echo "Error: Failed to unmount the file systems. Some of them remain mounted." >&2
+               exit 1
+       fi
+       message_echo "Unmounting done."
+}
+
+# ============= Destroy the chroot environment =============
+fs_destroy ()
+{
+       local systembase
+       systembase=$1
+       fs_chk_safety_basedir "$opt_basedir" || return 0
+       [ ! -d "$opt_basedir" ] && return
+       fs_terminate_if_unmount_unavailable "$systembase"
+       fs_unmount "$systembase"
+       chflags -R noschg "$opt_basedir"
+       rm -rf "$opt_basedir"
+}
diff --git a/lib/chroot/libmain.sh b/lib/chroot/libmain.sh
new file mode 100644 (file)
index 0000000..21601cd
--- /dev/null
@@ -0,0 +1,20 @@
+#!/bin/sh -e
+# ==============================================================================
+# portsreinstall library script
+# Overlay onto lib/libmain.sh for portsreinstall-chroot
+# - Common functions of main programs -
+# Copyright (C) 2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# This software is distributed under the 2-Clause BSD License.
+# ==============================================================================
+
+# ============= Set termination messages for special commands =============
+main_set_termination_messages_special ()
+{
+       temp_terminate_process ()
+       {
+               local errno
+               errno=${1:-0}
+               ! fs_chk_unmount && misc_chk_mount_privilege && fs_unmount
+               temp_terminate_process_common "$errno"
+       }
+}
diff --git a/lib/chroot/libmessage.sh b/lib/chroot/libmessage.sh
new file mode 100644 (file)
index 0000000..1691243
--- /dev/null
@@ -0,0 +1,18 @@
+#!/bin/sh -e
+# ==============================================================================
+# portsreinstall library script
+# Overlay onto lib/libmessage.sh for portsreinstall-chroot
+# - Messages -
+# Copyright (C) 2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# This software is distributed under the 2-Clause BSD License.
+# ==============================================================================
+
+# ============= Output the brief description =============
+message_brief_description ()
+{
+       cat << eof
+ -- Builder chroot launcher utility for portsreinstall,
+ -- The ports upgrading utility for massive forced reinstallation
+ -- And for those who are pursuing the perfect packages environment
+eof
+}
diff --git a/lib/chroot/liboptions.sh b/lib/chroot/liboptions.sh
new file mode 100644 (file)
index 0000000..3283717
--- /dev/null
@@ -0,0 +1,46 @@
+#!/bin/sh -e
+# ==============================================================================
+# portsreinstall library script
+# Overlay onto lib/liboptions.sh for portsreinstall-chroot
+# - Command line options -
+# Copyright (C) 2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# This software is distributed under the 2-Clause BSD License.
+# ==============================================================================
+
+# ============= Database of options which are given at each run and not saved =============
+# [Syntax of option databases]
+# short_name, long_name, variable, defult_vaule, set_value
+# Columns are delimited by tab characters.
+options_db_onetime ()
+{
+       cat << eof
+h      help    opt_help_mode   0       1
+h      short-help      opt_help_mode   0       1
+H      long-help       opt_help_mode   0       2
+V      show-version    opt_show_version        no      yes
+a      batch-mode      opt_batch_mode  no      yes
+E      extra-dirs-delim        opt_extra_dirs_delim    ,       :
+M      reset-minor-options     opt_reset_minor_options no      yes
+S      no-opening-message      opt_no_opening_message  no      yes
+eof
+}
+
+# ============= Database of options which are saved and not renewable until the temporary database is cleaned =============
+options_db_saved_and_non_renewable ()
+{
+       cat << eof
+b      basedir opt_basedir     /home/.${APPNAME}       :
+c      suppress-clean-obsolete-database        opt_suppress_obsolete_db_clean  no      yes
+d      invalidate-mount-privilege      opt_invalidate_mount_privilege  no      yes
+e      extra-dirs      opt_extra_dirs  ''      :
+p      load-pkgtoolsconf-as-default    opt_load_pkgtoolsconf   undef   default
+P      load-pkgtoolsconf-as-override   opt_load_pkgtoolsconf   undef   override
+Q      ignore-pkgtoolsconf     opt_load_pkgtoolsconf   undef   no
+eof
+}
+
+# ============= Regularize the option value =============
+options_regularize ()
+{
+       opt_basedir=`misc_global_path "$opt_basedir"`
+}
diff --git a/lib/chroot/libusage.sh b/lib/chroot/libusage.sh
new file mode 100644 (file)
index 0000000..4b0904e
--- /dev/null
@@ -0,0 +1,49 @@
+#!/bin/sh -e
+# ==============================================================================
+# portsreinstall library script
+# Overlay onto lib/libusage.sh for portsreinstall-chroot
+# - Help messages -
+# Copyright (C) 2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# This software is distributed under the 2-Clause BSD License.
+# ==============================================================================
+
+# ============= Content of the short help =============
+usage_short_content ()
+{
+       cat << eof
+USAGE: portsreinstall-chroot [OPTIONS] [--] [command]
+
+[OPTIONS]
+ <Group 1: Just show messages and exit without operation>
+ -H : Show a long help whose content is the same as the manual page.
+ -h : Show this short help.
+ -V : Show the current version.
+ <Group 2: Effective anytime>
+ -a : Suppress messages to be batch-friendly.
+ -E delimiter(s) : Custom delimiter character(s) for -e option.
+ -S : Suppress the credit and opening messages.
+ <Group 3: Saved and not renewable until cleaning>
+ -b : Base directory of the chroot environment (default: /home/.portsreinstall-chroot).
+ -c : Suppress cleaning the temporary database even if its obsolete.
+ -d : Forcibly invalidate the privilege of mounting/unmounting file systems.
+ -e dir[,dir2[,...]] : Extra directories to mount for the chroot environment.
+ -P : Import settings from pkgtools.conf(5) as the secondary if exists.
+ -p : Import settings from pkgtools.conf(5) as the primary if exists (default).
+ -Q : Ignore pkgtools.conf(5) even if it exists.
+
+[ARGUMENTS]
+ command:
+            do (default)
+          | enter
+          | mount | unmount
+          | sync
+          | clean [normal] | clean force
+          | options
+[DESCRIPTIONS]
+ This utility assists to update packages by creating and using chroot environment for building. The chroot environment is first created by forking the host environment, and the user is asked to complete update of packages at the chroot environment.
+
+[ROBUSTNESS AGAINST TERMINATION AND RESTART]
+ Execution of the commands except "clean" and "options" commands can be terminated at any points and restarted from there with the same options saved in the temporary database (independent among utilities). The saved options can be changed by the ways depending on the assigned groups of the options. The options and execution progress are reset to the default by "clean" command.
+eof
+}
index 9efcfaa..a12496f 100644 (file)
@@ -1,8 +1,8 @@
 #!/bin/sh -e
 # ==============================================================================
 # portsreinstall library script
-# - Operations of commands as well as check of command line arguments -
-# Copyright (C) 2013-2017 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# - Interface of libraries for operations of commands as well as check of command line arguments -
+# Copyright (C) 2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
 # This software is distributed under the 2-Clause BSD License.
 # ==============================================================================
 
@@ -19,6 +19,12 @@ COMMAND_SHOW_OPTIONS=
 COMMAND_SHOW_DEPTAG=
 COMMAND_SHOW_LEVEL=
 
+# ============= Check the necessity of opening notice =============
+command_all_chk_need_opening_notice ()
+{
+       :
+}
+
 # ============= Check the number of following command line arguments (in case glob arguments are needed) =============
 _command_parse_args__chk_glob_args ()
 {
@@ -42,248 +48,13 @@ _command_parse_args__chk_no_arg ()
 }
 
 # ============= Execute command operations before getting the temporary database ready =============
-command_exec_before_db_creation ()
+command_all_exec_before_db_creation ()
 {
-       local COMMAND_RESTART COMMAND_MODE COMMAND_OPERATION
-       COMMAND_RESTART="$@"
-       COMMAND_MODE=${1:-do}
-       shift || :
-       case $COMMAND_MODE in
-       clean)
-               COMMAND_OPERATION=${1:-normal}
-               shift || :
-               case $COMMAND_OPERATION in
-               force)
-                       message_echo "INFO: The temporary database is tried to be cleaned up without checking the privilege."
-                       rm -rf "${DBDIR}"
-                       message_echo "Done"
-                       exit
-                       ;;
-               esac
-               _command_parse_args__chk_no_arg $#
-               ;;
-       esac
 }
 
 # ============= Check and parse command line arguments =============
-command_parse_args ()
+command_all_parse_args ()
 {
-       local num_args_init
-       num_args_init=$#
-       COMMAND_RESTART="$@"
-       COMMAND_MODE=${1:-do}
-       shift || :
-       case $COMMAND_MODE in
-       clean)
-               COMMAND_OPERATION=${1:-normal}
-               shift || :
-               case $COMMAND_OPERATION in
-               normal)
-                       misc_chk_privilege
-                       ;;
-               esac
-               _command_parse_args__chk_no_arg $#
-               ;;
-       reset)
-               misc_chk_privilege
-               COMMAND_OPERATION=${1:-all}
-               shift || :
-               case $COMMAND_OPERATION in
-               all|keepopts)
-                       ;;
-               *)
-                       message_echo "ERROR: Invalid operation [$COMMAND_OPERATION]; it must be empty, \"all\" or \"keepopts\"." >&2
-                       exit 1
-                       ;;
-               esac
-               _command_parse_args__chk_no_arg $#
-               ;;
-       ok|taboo|need|noneed)
-               misc_chk_privilege
-               [ $COMMAND_MODE = ok ] && database_query_chk_preparation_completion
-               temp_warn_obsolete_temp_db >&2
-               COMMAND_OPERATION=$1
-               shift || :
-               case $COMMAND_OPERATION in
-               add|del)
-                       ;;
-               '')
-                       message_echo "ERROR: Missing operation which must be \"add\" or \"del\"." >&2
-                       exit 1
-                       ;;
-               *)
-                       message_echo "ERROR: Invalid operation [$COMMAND_OPERATION]; it must be \"add\" or \"del\"." >&2
-                       exit 1
-                       ;;
-               esac
-               _command_parse_args__chk_glob_args $#
-               ;;
-       reselect)
-               misc_chk_privilege
-               database_query_chk_preparation_completion
-               temp_warn_obsolete_temp_db >&2
-               COMMAND_OPERATION=$1
-               shift || :
-               case $COMMAND_OPERATION in
-               leaves)
-                       if [ -e "${DBDIR}/inspected_ports_only_partially" ]
-                       then
-                               message_echo "ERROR: Leaf ports cannot be analyzed because the dependency inspection is partial." >&2
-                               message_echo "Executing redo command with -N option by disabling -o option fixes this situation." >&2
-                               exit 1
-                       fi
-                       ;;
-               obsolete)
-                       ;;
-               '')
-                       message_echo "ERROR: Missing operation which must be \"leaves\" or \"obsolete\"." >&2
-                       exit 1
-                       ;;
-               *)
-                       message_echo "ERROR: Invalid operation [$COMMAND_OPERATION]; it must be \"leaves\" or \"obsolete\"." >&2
-                       exit 1
-                       ;;
-               esac
-               _command_parse_args__chk_glob_args $#
-               ;;
-       save)
-               misc_chk_privilege
-               if [ ! -d "${DBDIR}" ]
-               then
-                       message_echo "ERROR: The temporary database has not been created yet." >&2
-                       exit 1
-               fi
-               COMMAND_SAVE_DIR=$1
-               shift || :
-               _command_parse_args__chk_no_arg $#
-               if [ -z "$COMMAND_SAVE_DIR" ]
-               then
-                       message_echo "ERROR: Directory to save the temporary database archive is not specified." >&2
-                       exit 1
-               fi
-               if [ ! -d "$COMMAND_SAVE_DIR" ]
-               then
-                       message_echo "ERROR: Directory [$COMMAND_SAVE_DIR] is not found." >&2
-                       exit 1
-               fi
-               ;;
-       load)
-               misc_chk_privilege
-               if [ -e "${DBDIR}/in_use" ]
-               then
-                       message_echo "ERROR: A temporary database exists." >&2
-                       message_echo "You must execute" >&2
-                       message_echo "        ${APPNAME} clean" >&2
-                       message_echo "before executing \"load\" command." >&2
-                       exit 1
-               fi
-               COMMAND_LOAD_FILE=$1
-               shift || :
-               _command_parse_args__chk_no_arg $#
-               if [ -z "$COMMAND_LOAD_FILE" ]
-               then
-                       message_echo "ERROR: No temporary database archive is specified." >&2
-                       exit 1
-               fi
-               if [ ! -f "$COMMAND_LOAD_FILE" ]
-               then
-                       message_echo "ERROR: The temporary database archive is not found." >&2
-                       exit 1
-               fi
-               COMMAND_LOAD_FILE=`realpath "$COMMAND_LOAD_FILE"`
-               ;;
-       glob)
-               _command_parse_args__chk_glob_args $#
-               ;;
-       options)
-               _command_parse_args__chk_no_arg $#
-               ;;
-       reconf|rmconf|forget|escape|restore)
-               misc_chk_privilege
-               temp_warn_obsolete_temp_db >&2
-               _command_parse_args__chk_glob_args $#
-               ;;
-       pkgsanity)
-               misc_chk_privilege
-               temp_warn_obsolete_temp_db >&2
-               ;;
-       show)
-               database_query_chk_preparation_completion
-               temp_warn_obsolete_temp_db >&2
-               if ! expr "$1" : '@.*' > /dev/null
-               then
-                       COMMAND_SHOW_SUBJECT=${1:-todo}
-                       shift || :
-               else
-                       COMMAND_SHOW_SUBJECT=todo
-               fi
-               COMMAND_SHOW_OPTIONS=$1
-               if expr "$COMMAND_SHOW_OPTIONS" : '@.*' > /dev/null
-               then
-                       COMMAND_SHOW_DEPTAG=`expr "$COMMAND_SHOW_OPTIONS," : '@\(.*\)' | cut -d , -f 1` || :
-                       COMMAND_SHOW_LEVEL=`expr "$COMMAND_SHOW_OPTIONS," : '@\(.*\)' | cut -d , -f 2` || :
-                       case $COMMAND_SHOW_DEPTAG in
-                       all|run|build|'')       ;;
-                       *)
-                               message_echo "ERROR: Invalid show option [$COMMAND_SHOW_OPTIONS]." >&2
-                               exit 1
-                               ;;
-                       esac
-                       case $COMMAND_SHOW_LEVEL in
-                       full|direct|'') ;;
-                       *)
-                               message_echo "ERROR: Invalid show option [$COMMAND_SHOW_OPTIONS]." >&2
-                               exit 1
-                               ;;
-                       esac
-                       shift || :
-               fi
-               case $COMMAND_SHOW_SUBJECT in
-               todo|done|redo|resolved|failure|taboo|need|noneed|restored|deleted|conflict)
-                       _command_parse_args__chk_no_arg $#
-                       ;;
-               initrequirements|requirements|initdependents|dependents|status)
-                       _command_parse_args__chk_glob_args $#
-                       ;;
-               *)
-                       message_echo "ERROR: Invalid subject [$COMMAND_SHOW_SUBJECT]." >&2
-                       exit 1
-                       ;;
-               esac
-               ;;
-       all|prepare)
-               COMMAND_DO_MODE=$COMMAND_MODE
-               COMMAND_MODE=do
-               misc_chk_privilege
-               temp_warn_obsolete_temp_db >&2
-               _command_parse_args__chk_no_arg $#
-               ;;
-       redo|do)
-               COMMAND_DO_MODE=${1:-all}
-               shift || :
-               case $COMMAND_DO_MODE in
-               all|prepare);;
-               *)
-                       message_echo "ERROR: Invalid operation mode [$COMMAND_DO_MODE]." >&2
-                       exit 1
-                       ;;
-               esac
-               misc_chk_privilege
-               temp_warn_obsolete_temp_db >&2
-               _command_parse_args__chk_no_arg $#
-               if [ "$COMMAND_DO_MODE" = prepare ]
-               then
-                       COMMAND_RESTART=prepare
-               else
-                       COMMAND_RESTART=
-               fi
-               ;;
-       *)
-               message_echo "ERROR: Invalid command [$COMMAND_MODE]." >&2
-               exit 1
-               ;;
-       esac
-       COMMAND_SHIFT=$(($num_args_init - $#))
 }
 
 # ============= Notify that option settings are reset =============
@@ -293,724 +64,44 @@ command_exec_without_pkgtools__notify_reset_options ()
 }
 
 # ============= Execute command operations which do not need package tools =============
-command_exec_without_pkgtools ()
+command_all_exec_without_pkgtools ()
 {
-       local dbdir_parent 
-       case $COMMAND_MODE in
-       clean)
-               message_echo "Starting to clean up the temporary database..."
-               command_exec_without_pkgtools__notify_reset_options
-               rm -rf "${DBDIR}"
-               message_echo "Done"
-               exit
-               ;;
-       load)
-               message_echo "Starting to load the temporary database from the archive..."
-               command_exec_without_pkgtools__notify_reset_options
-               dbdir_parent=`dirname "${DBDIR}"`
-               [ -d "$dbdir_parent" ] || mkdir -p "$dbdir_parent"
-               tar xzf "$COMMAND_LOAD_FILE" -C "$dbdir_parent" --exclude "*/.lock"
-               message_echo "Done"
-               exit
-               ;;
-       esac
 }
 
+
 # ============= Notify that option settings are ignored because of no effect =============
 _command_exec_irrespective_of_saved_options__notify_ignored_options ()
 {
+       [ $opt_no_opening_message = yes ] && return
        message_echo "NOTE: Option settings are ignored because they have no effect on this command."
 }
 
-# ============= Operations of forget command =============
-command_forget ()
+# ============= Execute command operations which are irrespective of option settings =============
+command_all_exec_irrespective_of_saved_options ()
 {
-       message_echo "The temporary database is trying to forget about the specified ports as much as possible."
-       message_echo "Concretely, the data on each of the specified ports and their requirements/dependents is removed unless initially installed or required by other preserved ports."
-       message_echo
-       
-       # Preparation for inspection of the specified ports
-       PROGRAM_DEPENDS=''
-       _program_exec_and_record_completion__operation ()
-       {
-               message_section_title "Preparation for inspection of the specified ports"
-               rm -rf "${DBDIR}/forget"
-               mkdir "${DBDIR}/forget"
-               for list in masters remove_scope
-               do
-                       rm -f "${DBDIR}/stage.loop_list/forget_$list"*
-               done
-               message_echo
-       }
-       program_exec_and_record_completion FORGET::PREPARATION_INSPECT_MASTER
-       
-       # (Re)initialization of the specified ports to inspect
-       pkgsys_eval_ports_glob "$@" > ${DBDIR}/stage.loop_list/forget_masters
-       
-       # Inspection of the specified ports
-       PROGRAM_DEPENDS='FORGET::PREPARATION_INSPECT_MASTER'
-       _program_exec_restartable_loop_operation__routine ()
-       {
-               local origin origin_orig
-               origin=$1
-               if [ -e "${DBDIR}/REVERSE_REPLACE.complete_sed_pattern" ]
-               then
-                       origin_orig=`echo "$origin" \
-                               | sed -E -f "${DBDIR}/REVERSE_REPLACE.complete_sed_pattern"`
-               else
-                       origin_orig=$origin
-               fi
-               if [ ! -e "${DBDIR}/initial/$origin/installed_version" \
-                       -a ! -e "${DBDIR}/initial/$origin_orig/installed_version" \
-                       -a `cat "${DBDIR}/requires/$origin/dependents.all.full" 2> /dev/null | wc -l` -eq 0 ]
-               then
-                       message_echo "$origin"
-                       echo "$origin" >> ${DBDIR}/forget/remove.master
-                       cat "${DBDIR}/requires/$origin/requirements.all.full" \
-                               2> /dev/null >> ${DBDIR}/forget/remove.scope || :
-                       database_build_forget "$origin"
-               fi
-       }
-       _program_exec_and_record_completion__operation ()
-       {
-               message_section_title "Inspection of the specified ports"
-               message_echo "----------------"
-               program_exec_restartable_loop_operation forget_masters
-               message_echo "----------------"
-               cat "${DBDIR}/forget/remove.scope" 2> /dev/null \
-                       | sort -u > ${DBDIR}/forget/remove.scope.tmp
-               mv "${DBDIR}/forget/remove.scope.tmp" "${DBDIR}/forget/remove.scope"
-               cat "${DBDIR}/forget/remove.master" "${DBDIR}/forget/remove.scope" 2> /dev/null \
-                       | str_escape_regexp_filter \
-                       | sed 's/^/^/;s/$/$/' > ${DBDIR}/forget/remove.scope.grep_pattern
-               ln -f "${DBDIR}/forget/remove.scope" "${DBDIR}/stage.loop_list/forget_remove_scope"
-               message_echo
-       }
-       program_exec_and_record_completion FORGET::INSPECT_MASTER
-       
-       # Inspection of the requirements of the specified ports to remove
-       PROGRAM_DEPENDS='FORGET::INSPECT_MASTER'
-       _program_exec_restartable_loop_operation__routine ()
-       {
-               local origin origin_orig
-               origin=$1
-               if [ -e "${DBDIR}/REVERSE_REPLACE.complete_sed_pattern" ]
-               then
-                       origin_orig=`echo "$origin" \
-                               | sed -E -f "${DBDIR}/REVERSE_REPLACE.complete_sed_pattern"`
-               else
-                       origin_orig=$origin
-               fi
-               if [ ! -e "${DBDIR}/initial/$origin/installed_version" \
-                       -a ! -e "${DBDIR}/initial/$origin_orig/installed_version" ] \
-                       && ! grep -v -E -f "${DBDIR}/forget/remove.scope.grep_pattern" \
-                               "${DBDIR}/requires/$origin/dependents.all.full" \
-                               > /dev/null 2>&1
-               then
-                       message_echo "$origin"
-                       database_build_forget "$origin"
-                       echo "$origin" >> ${DBDIR}/forget/remove
-               fi
-       }
-       _program_exec_and_record_completion__operation ()
-       {
-               message_section_title "Inspection of the requirements of the specified ports to remove"
-               message_echo "----------------"
-               program_exec_restartable_loop_operation forget_remove_scope
-               message_echo "----------------"
-               cat "${DBDIR}/forget/remove.master" "${DBDIR}/forget/remove" 2> /dev/null \
-                       | str_escape_regexp_filter \
-                       | sed 's/^/^/;s/$/$/' > ${DBDIR}/forget/remove.grep_pattern
-               cat "${DBDIR}/inspected_ports.update" 2> /dev/null | sort -u \
-                       | grep -v -E -f "${DBDIR}/forget/remove.grep_pattern" \
-                               > ${DBDIR}/inspected_ports.update.tmp || :
-               mv "${DBDIR}/inspected_ports.update.tmp" "${DBDIR}/inspected_ports.update"
-               message_echo
-       }
-       program_exec_and_record_completion FORGET::INSPECT_REQUIREMENTS_OF_REMOVED_PORTS
-       
-       # Set up so that ports are inspected again in the building process of the temporary database
-       program_deregister_stage_complete INSPECT_ALL_DEPENDENCIES
-       
-       # Clean up the database for this command because it is no more effective
-       program_deregister_stage_complete FORGET::PREPARATION_INSPECT_MASTER
-       message_echo "Done"
 }
 
-# ============= Execute command operations which are irrespective of option settings =============
-command_exec_irrespective_of_saved_options ()
+# ============= Execute command operations which should be done without upgrade of tools =============
+command_all_exec_before_tools_upgrade ()
 {
-       local dbfile tmp_manually_done_diff evalated_globs dbdir_parent dbdir_node arcfile grandtitle title isfirst origin origin_regexp backup_pkg origin_orig origin_replace pkg_orig tmp_done_orig tmp_pkgsanity nlines iline pkg make_target
-       case $COMMAND_MODE in
-       ok)
-               dbfile=${DBDIR}/manually_done.list
-               [ -e "$dbfile" ] || touch "$dbfile"
-               cp "$dbfile" "$dbfile.tmp"
-               case $COMMAND_OPERATION in
-               add)
-                       pkgsys_register_evaluated_globs add "$dbfile.tmp" "$@"
-                       message_echo "`str_linearize_list_and \"$*\"` is/are registered to the list of manually resolved ports"
-                       ;;
-               del)
-                       pkgsys_register_evaluated_globs remove "$dbfile.tmp" "$@"
-                       message_echo "`str_linearize_list_and \"$*\"` is/are deregistered from the list of manually resolved ports"
-                       ;;
-               esac
-               tmp_manually_done_diff_old=${TMPDIR}/command_exec_irrespective_of_saved_options:manually_done.list.diff_old
-               tmp_manually_done_diff_new=${TMPDIR}/command_exec_irrespective_of_saved_options:manually_done.list.diff_new
-               if fileedit_manipulate_old_new_lines "$dbfile" "$dbfile.tmp" \
-                       "$tmp_manually_done_diff_old" "$tmp_manually_done_diff_new"
-               then
-                       while read origin
-                       do
-                               database_record_failure "$origin"
-                       done < $tmp_manually_done_diff_old
-                       while read origin
-                       do
-                               database_record_success "$origin"
-                       done < $tmp_manually_done_diff_new
-               fi
-               mv "$dbfile.tmp" "$dbfile"
-               _command_exec_irrespective_of_saved_options__notify_ignored_options
-               message_echo "Now the following ports have been manually resolved:"
-               message_cat "$dbfile"
-               exit
-               ;;
-       taboo)
-               evalated_globs=`str_linearize_list_and "$@"`
-               case $COMMAND_OPERATION in
-               add)
-                       pkgsys_register_evaluated_globs add "${DBDIR}/taboo.list" "$@"
-                       message_echo "$evalated_globs is/are registered to the list of ports to be ignored."
-                       ;;
-               del)
-                       pkgsys_register_evaluated_globs remove "${DBDIR}/taboo.list" "$@"
-                       message_echo "$evalated_globs is/are deregistered from the list of ports to be ignored."
-                       ;;
-               esac
-               fileedit_combine_lists "${DBDIR}/conf/TABOO:PORTS.parsed" "${DBDIR}/taboo.list" > ${DBDIR}/taboo.all.list
-               _command_exec_irrespective_of_saved_options__notify_ignored_options
-               message_echo "Now the following ports are registered to be ignored:"
-               message_cat "${DBDIR}/taboo.all.list"
-               exit
-               ;;
-       need)
-               evalated_globs=`str_linearize_list_and "$@"`
-               case $COMMAND_OPERATION in
-               add)
-                       pkgsys_register_evaluated_globs add "${DBDIR}/need.list" "$@"
-                       message_echo "$evalated_globs is/are registered to the list of necessary ports."
-                       ;;
-               del)
-                       pkgsys_register_evaluated_globs remove "${DBDIR}/need.list" "$@"
-                       message_echo "$evalated_globs is/are deregistered from the list of necessary ports."
-                       ;;
-               esac
-               str_escape_regexp_filter < ${DBDIR}/need.list \
-                       | sed 's/^/^/; s/$/$/' > ${DBDIR}/need.grep_pattern
-               {
-                       sed -E -f "${DBDIR}/REPLACE.complete_sed_pattern" "${DBDIR}/need.list" || :
-                       cat "${DBDIR}/need.list" || :
-               } 2> /dev/null | sort -u > ${DBDIR}/need.with_replaced.list
-               program_deregister_stage_complete DETERMINE_SPECIFIED_TARGETS
-               _command_exec_irrespective_of_saved_options__notify_ignored_options
-               message_echo "Now the following ports are registered to be necessary:"
-               message_cat "${DBDIR}/need.list"
-               exit
-               ;;
-       noneed)
-               evalated_globs=`str_linearize_list_and "$@"`
-               case $COMMAND_OPERATION in
-               add)
-                       pkgsys_register_evaluated_globs add "${DBDIR}/noneed.list" "$@"
-                       message_echo "$evalated_globs is/are registered to the list of unnecessary ports."
-                       ;;
-               del)
-                       pkgsys_register_evaluated_globs remove "${DBDIR}/noneed.list" "$@"
-                       message_echo "$evalated_globs is/are deregistered from the list of unnecessary ports."
-                       ;;
-               esac
-               program_deregister_stage_complete INSPECT_PRIMARY_LEAF_PORTS
-               _command_exec_irrespective_of_saved_options__notify_ignored_options
-               message_echo "Now the following ports are registered to be unnecessary:"
-               message_cat "${DBDIR}/noneed.list"
-               exit
-               ;;
-       reselect)
-               case $COMMAND_OPERATION in
-               leaves)
-                       if ! deinstall_select_leaf_ports_to_delete force
-                       then
-                               case $? in
-                               2)
-                                       message_echo "INFO: No leaf port is found."
-                                       ;;
-                               3)
-                                       message_echo "INFO: Leaf ports are undefined because requirements of some ports are not fully inspected."
-                                       ;;
-                               esac
-                       else
-                               program_deregister_stage_complete COLLECT_LEAF_PORTS_TO_DELETE
-                       fi
-                       ;;
-               obsolete)
-                       if ! deinstall_select_obsolete_ports_to_delete force
-                       then
-                               case $? in
-                               2)
-                                       message_echo "INFO: No obsolete package is found."
-                                       ;;
-                               esac
-                       else
-                               program_deregister_stage_complete COLLECT_OBSOLETE_PORTS_TO_DELETE
-                       fi
-                       ;;
-               esac
-               exit
-               ;;
-       save)
-               dbdir_parent=`dirname "${DBDIR}"`
-               dbdir_node=`basename "${DBDIR}"`
-               arcfile=`realpath "$COMMAND_SAVE_DIR"`/${APPNAME}_`date +%Y%m%d_%H%M%S`.tar.gz
-               _command_exec_irrespective_of_saved_options__notify_ignored_options
-               message_echo "Starting to save the temporary database as [$arcfile]..."
-               tar czf "$arcfile" -C "$dbdir_parent" "$dbdir_node"
-               message_echo "Done"
-               exit
-               ;;
-       glob)
-               _command_exec_irrespective_of_saved_options__notify_ignored_options
-               message_echo "Evaluated port origins are as follows:"
-               pkgsys_eval_ports_glob "$@"
-               exit
-               ;;
-       reconf|rmconf)
-               _command_exec_irrespective_of_saved_options__notify_ignored_options
-               case $COMMAND_MODE in
-               reconf)
-                       message_echo "Reconfigure the specified port options."
-                       make_target=config
-                       ;;
-               rmconf)
-                       message_echo "The specified port options are reset to the default."
-                       make_target=rmconfig
-                       ;;
-               esac
-               message_echo "Affected parts of the temporary database are reset automatically."
-               for origin in `pkgsys_eval_ports_glob "$@"`
-               do
-                       origin_regexp=`str_escape_regexp "$origin"`
-                       if grep -q -E "^$origin_regexp$" "${DBDIR}/inspected_ports" 2> /dev/null
-                       then
-                               database_build_make "$origin" $make_target
-                               database_build_patch_reconf "$origin"
-                       else
-                               message_echo "$origin (not inspected)"
-                               continue
-                       fi
-               done
-               program_deregister_stage_complete INSPECT_ALL_DEPENDENCIES
-               message_echo "Done"
-               exit
-               ;;
-       forget)
-               _command_exec_irrespective_of_saved_options__notify_ignored_options
-               command_forget "$@"
-               exit
-               ;;
-       escape)
-               _command_exec_irrespective_of_saved_options__notify_ignored_options
-               message_echo "Backing up and deleting the following packages for a temporary escape:"
-               message_echo
-               for origin in `pkgsys_eval_ports_glob "$@"`
-               do
-                       pkgsys_register_evaluated_globs add "${DBDIR}/taboo.list" "$origin"
-                       message_echo "  Registered $origin as taboo."
-                       pkg=`pkg_info_qO "$origin"` || continue
-                       [ -n "$pkg" ] || continue
-                       if backup_pkg=`pkgsys_get_backup_pkg "$origin"`
-                       then
-                               message_echo "INFO: A backup package for $pkg ($origin) already exists as $backup_pkg."
-                       elif backup_pkg=`pkgsys_create_backup_pkg "$pkg" "${DBDIR}/backup_packages"`
-                       then
-                               message_echo "  Backed up $pkg ($origin) into $backup_pkg"
-                       else
-                               message_echo "ERROR: Failed to back up $pkg ($origin)." >&2
-                               message_echo >&2
-                               continue
-                       fi
-                       pkg_delete_f "$pkg" || \
-                       {
-                               message_echo "ERROR: Failed to deinstall $pkg ($origin)." >&2
-                               message_echo >&2
-                       }
-                       message_echo "  Deinstalled $pkg ($origin)."
-                       message_echo
-               done
-               fileedit_combine_lists "${DBDIR}/conf/TABOO:PORTS.parsed" "${DBDIR}/taboo.list" > ${DBDIR}/taboo.all.list
-               message_echo "Done"
-               exit
-               ;;
-       restore)
-               _command_exec_irrespective_of_saved_options__notify_ignored_options
-               message_echo "Restoring the following temporary escaped packages:"
-               message_echo
-               tmp_done_orig=${TMPDIR}/command_exec_irrespective_of_saved_options::restore::done_orig
-               cp /dev/null "$tmp_done_orig"
-               for origin in `pkgsys_eval_ports_glob "$@"`
-               do
-                       pkgsys_register_evaluated_globs remove "${DBDIR}/taboo.list" "$origin"
-                       message_echo "  Deregistered $origin from taboo."
-                       origin_regexp=`str_escape_regexp "$origin"`
-                       grep -E -q "^$origin_regexp$" "$tmp_done_orig" || :
-                       if pkg_info_eO "$origin"
-                       then
-                               pkg=`pkg_info_qO "$origin"` || :
-                               message_echo "WARNING: $pkg ($origin) is already installed." >&2
-                               message_echo >&2
-                               continue
-                       fi
-                       origin_orig=`echo "$origin" \
-                               | sed -E -f "${DBDIR}/REVERSE_REPLACE.complete_sed_pattern"`
-                       if [ "x$origin_orig" = "x$origin" ] && pkg_info_eO "$origin_orig"
-                       then
-                               pkg_orig=`pkg_info_qO "$origin_orig"` || :
-                               message_echo "WARNING: An original version of $origin ($pkg_orig, $origin_orig) is already installed." >&2
-                               message_echo >&2
-                               continue
-                       fi
-                       origin_replace=`echo "$origin" \
-                               | sed -E -f "${DBDIR}/REPLACE.complete_sed_pattern"`
-                       if [ "x$origin_replace" != "x$origin" ]
-                       then
-                               if pkg_info_eO "$origin_replace"
-                               then
-                                       pkg_replace=`pkg_info_qO "$origin_replace"` || :
-                                       message_echo "WARNING: A replacement of $origin ($pkg_replace, $origin_replace) is already installed." >&2
-                                       message_echo >&2
-                                       continue
-                               fi
-                               if backup_pkg=`pkgsys_get_backup_pkg "$origin_replace" 2> /dev/null`
-                               then
-                                       message_echo "INFO: $origin is replaced with $origin_replace ($pkg_replace)."
-                                       echo "$origin_replace" >> $tmp_done_orig
-                                       origin=$origin_replace
-                               fi
-                       else
-                               backup_pkg=
-                       fi
-                       if [ -z "$backup_pkg" ] && ! backup_pkg=`pkgsys_get_backup_pkg "$origin" 2> /dev/null`
-                       then
-                               message_echo "ERROR: Backup for $origin is not found." >&2
-                               message_echo >&2
-                               continue
-                       fi
-                       pkg=`pkgsys_pkgarc_to_pkgname "$backup_pkg"`
-                       if reinstall_chk_forbidden_conflicts "$pkg"
-                       then
-                               message_echo "WARNING: $pkg ($origin) is skipped because it conflicts with installed packages." >&2
-                               message_echo >&2
-                               continue
-                       fi
-                       if ! pkg_add_fF "$backup_pkg"
-                       then
-                               message_echo "ERROR: Failed to restore $pkg ($origin)." >&2
-                               message_echo >&2
-                       fi
-                       message_echo "  Restored $pkg ($origin)."
-                       message_echo
-               done
-               fileedit_combine_lists "${DBDIR}/conf/TABOO:PORTS.parsed" "${DBDIR}/taboo.list" > ${DBDIR}/taboo.all.list
-               message_echo "Done"
-               exit
-               ;;
-       pkgsanity)
-               tmp_pkgs=${TMPDIR}/command_exec_irrespective_of_saved_options:pkgs
-               tmp_orgs=${TMPDIR}/command_exec_irrespective_of_saved_options:orgs
-               tmp_pkgs_for_an_org=${TMPDIR}/command_exec_irrespective_of_saved_options:pkgs_for_an_org
-               tmp_pkgs_for_an_org_msg=${TMPDIR}/command_exec_irrespective_of_saved_options:pkgs_for_an_org_msg
-               _command_exec_irrespective_of_saved_options__notify_ignored_options
-               if [ $# -eq 0 ]
-               then
-                       message_echo "Sanity check of the installed files for each package:"
-                       message_echo
-                       pkg_info_Ea > $tmp_pkgs
-                       pkg_info_qoa > $tmp_orgs
-               else
-                       message_echo "Examining the installed files for each specified package:"
-                       message_echo
-                       pkgsys_eval_ports_glob "$@" > $tmp_orgs
-                       while read origin
-                       do
-                               pkg_info_qO "$origin" || :
-                       done < $tmp_orgs | grep -v '^[[:space:]]*$' > $tmp_pkgs
-               fi
-               message_echo "<< Phase 1: Check and fix duplicated packages registrations for the same port origin >>"
-               message_echo
-               while read origin
-               do
-                       [ `pkg_info_qO "$origin" | wc -l` -gt 1 ] || continue
-                       pkg_info_qO "$origin" | while read pkg
-                       do
-                               echo "$((0+`pkg_check_sanity \"$pkg\" | wc -l`))" "$pkg"
-                       done | sort -g > $tmp_pkgs_for_an_org
-                       pkg_valid=`head -n 1 "$tmp_pkgs_for_an_org" | cut -d ' ' -f 2`
-                       message_echo "Port [$origin] has multiply registered packages."
-                       message_echo "The valid one will be [$pkg_valid]."
-                       message_echo "Invalid one(s) will be as follows and to be deleted:"
-                       sed 1d "$tmp_pkgs_for_an_org" | cut -d ' ' -f 2 > $tmp_pkgs_for_an_org_msg
-                       message_cat "$tmp_pkgs_for_an_org_msg"
-                       errout=/dev/stderr
-                       [ "x$opt_batch_mode" = xyes ] && errout=/dev/null
-                       if backup_pkg=`pkgsys_create_backup_pkg "$pkg_valid" "${DBDIR}/backup_packages"`
-                       message_echo
-                       then
-                               pkg_delete_f `cat "$tmp_pkgs_for_an_org"` 2> $errout || {
-                                       message_echo "WARNING: Deletion of the broken packages may not be fully successful, but continuing anyway." >&2
-                                       message_echo >&2
-                               }
-                               pkg_add_fF "$backup_pkg" || {
-                                       message_echo "WARNING: Reinstallation of the most valid package failed, but continuing anyway." >&2
-                                       message_echo >&2
-                               }
-                       else
-                               message_echo "WARNING: Backup of the most valid package failed, but continuing anyway." >&2
-                               pkg_delete_f `cat "$tmp_pkgs_for_an_org"` 2> $errout || {
-                                       message_echo "WARNING: Deletion of the broken packages may not be fully successful, but continuing anyway." >&2
-                                       message_echo >&2
-                               }
-                       fi
-               done < $tmp_orgs
-               
-               message_echo "<< Phase 2: Check and mark broken packages for reinstallation >>"
-               message_echo
-               nlines=`wc -l < $tmp_pkgs`
-               iline=1
-               while [ $iline -le $nlines ]
-               do
-                       pkg=`sed -n ${iline}p "$tmp_pkgs"`
-                       iline=$((${iline}+1))
-                       origin=`pkg_info_qo "$pkg"` || continue
-                       [ -n "$origin" ] || continue
-                       origin_regexp=`str_escape_regexp "$origin"`
-                       grep -q -E "^$origin_regexp$" "${DBDIR}/damaged_package" 2>/dev/null && continue
-                       pkgsys_sanitychk_pkgcontents "$pkg" is_reinstall_encouraged && continue
-                       if [ ! -d "${PORTSDIR}/$origin" ]
-                       then
-                               message_echo "WARNING: $pkg ($origin) is obsolete." >&2
-                               message_echo >&2
-                               continue
-                       fi
-                       if [ $is_reinstall_encouraged = no ]
-                       then
-                               if [ $opt_batch_mode = no ]
-                               then
-                                       message_echo "Do you want to reinstall it? (y/[n])"
-                                       message_query_yn_default_no || continue
-                               fi
-                       else
-                               if [ $opt_batch_mode = no ]
-                               then
-                                       message_echo "Do you want to reinstall it? ([y]/n)"
-                                       message_query_yn_default_yes || continue
-                               fi
-                               database_record_reconf_recover_sanity "$origin"
-                       fi
-               done
-               message_echo "Done"
-               exit
-               ;;
-       redo)
-               if [ $opt_reload_conf = yes ]
-               then
-                       program_deregister_stage_complete SAVE_PREV_CONF
-               fi
-               ;;
-       esac
 }
 
-# ============= Output of "options" command =============
-_command_exec_before_tools_upgrade__options ()
+# ============= Execute command operations which must be done before the database construction =============
+command_all_exec_before_build_database ()
 {
-       local opt_control group_reset group_remain reset_opts result_opts str_opt_control str_rstoption notice_reset notice_result
-       opt_control=$1
-       group_reset=$2
-       group_remain=$3
-       reset_opts=`options_inverse_parse $group_reset`
-       result_opts=`options_inverse_parse $group_remain`
-       if [ $is_batch_mode = yes ]
-       then
-               printf '%s\t%s\t%s\n' "$opt_control" "$reset_opts" "$result_opts"
-       else
-               str_opt_control=`echo "$opt_control" | sed -E 's/(.)/-\1 /g;s/ *$//'`
-               str_rstoption=Option`[ \`echo -n "$opt_control" | wc -c\` -ge 2 ] && echo s` || :
-               notice_reset=`[ -z "$reset_opts" ] && echo ' (nothing)'` || :
-               notice_result=`[ -z "$result_opts" ] && echo ' (default)'` || :
-               echo "$str_rstoption [$str_opt_control] will reset [$reset_opts]$notice_reset so that the settings become [$result_opts]$notice_result."
-       fi
 }
 
-# ============= Execute command operations which should be done without upgrade of tools =============
-command_exec_before_tools_upgrade ()
+# ============= Execute command operations of database construction =============
+command_all_exec_build_database ()
 {
-       local flag_filter_skip_unchanged flag_filter_only_target pkgnamedb dbsuffix list origin_target
-       case $COMMAND_MODE in
-       reset)
-               message_echo "Starting to reset the temporary database by preserving the initial snapshot of installed packages..."
-               program_chk_stage_complete INSPECT_ALL_DEPENDENCIES && touch "${DBDIR}/installed_ports.inspected"
-               find "${DBDIR}" -depth 1 \
-                       -not \( -name saved_options.sh \
-                               -or -name initial -or -name MYVERSION \
-                               -or -name backup_failure -or -name installed_ports\* \) \
-                       -exec rm -rf {} \; 2> /dev/null || :
-               touch "${DBDIR}/MYVERSION"
-               case $COMMAND_OPERATION in
-               all)
-                       command_exec_without_pkgtools__notify_reset_options
-                       rm -f "${DBDIR}/saved_options.sh"
-                       ;;
-               keepopts)
-                       message_echo "INFO: option settings are preserved."
-                       ;;
-               esac
-               find "${DBDIR}/initial" -depth 2 -type d \
-                       | sed -E 's|.*/([^/]+/[^/]+)$|\1|' > ${DBDIR}/inspected_ports.update
-               mkdir -p "${DBDIR}/stage.loop_list"
-               message_echo "Done"
-               exit
-               ;;
-       options)
-               ( set -e
-                       is_batch_mode=$opt_batch_mode
-                       options_set_default
-                       [ -e "${DBDIR}/saved_options.sh" ] && . "${DBDIR}/saved_options.sh"
-                       savedopts=`options_inverse_parse`
-                       if [ $is_batch_mode = yes ]
-                       then
-                               printf '\t%s\n' "$savedopts"
-                       else
-                               echo "The saved setting is [$savedopts]."
-                       fi
-                       _command_exec_before_tools_upgrade__options M \
-                               'renewable_anytime' 'non_renewable renewable_in_redo_on_target renewable_in_redo_on_conf'
-                       _command_exec_before_tools_upgrade__options N \
-                               'renewable_in_redo_on_target' 'non_renewable renewable_anytime renewable_in_redo_on_conf'
-                       _command_exec_before_tools_upgrade__options L \
-                               'renewable_in_redo_on_conf' 'non_renewable renewable_anytime renewable_in_redo_on_target'
-                       _command_exec_before_tools_upgrade__options MN \
-                               'renewable_anytime renewable_in_redo_on_target' 'non_renewable renewable_in_redo_on_conf'
-                       _command_exec_before_tools_upgrade__options ML \
-                               'renewable_anytime renewable_in_redo_on_conf' 'non_renewable renewable_in_redo_on_target'
-                       _command_exec_before_tools_upgrade__options NL \
-                               'renewable_in_redo_on_target renewable_in_redo_on_conf' 'non_renewable renewable_anytime'
-                       _command_exec_before_tools_upgrade__options MNL \
-                               'renewable_anytime renewable_in_redo_on_target renewable_in_redo_on_conf' 'non_renewable'
-               )
-               exit
-               ;;
-       show)
-               flag_filter_skip_unchanged=
-               flag_filter_only_target=
-               pkgnamedb='requires obsolete initial'
-               [ -n "$COMMAND_SHOW_DEPTAG" ] || COMMAND_SHOW_DEPTAG=`options_get_dependency_type`
-               [ -n "$COMMAND_SHOW_LEVEL" ] || COMMAND_SHOW_LEVEL=`options_get_dependency_level`
-               dbsuffix=$COMMAND_SHOW_DEPTAG.$COMMAND_SHOW_LEVEL
-               case $COMMAND_SHOW_SUBJECT in
-               todo|done|redo|resolved|failure|taboo|need|noneed|deleted|restored|conflict)
-                       database_query_show_single_list_exec "$COMMAND_SHOW_SUBJECT" \
-                               "$COMMAND_SHOW_DEPTAG" "$COMMAND_SHOW_LEVEL" || :
-                       ;;
-               initrequirements)
-                       grandtitle="Dependencies based on the initially installed packages"
-                       title="The following port(s) was/were required by %s:"
-                       list=requirements.$dbsuffix
-                       pkgnamedb='initial'
-                       [ $COMMAND_SHOW_DEPTAG = none ] && \
-                               message_echo "WARNING: This command has no meaning with the current options setting." >&2
-                       database_query_for_each_matching_port "$grandtitle" "$title" "$list" "$pkgnamedb" \
-                               "$COMMAND_SHOW_DEPTAG" "$COMMAND_SHOW_LEVEL" "$@"
-                       ;;
-               requirements)
-                       grandtitle="Dependencies based on the latest ports tree"
-                       title="The following port(s) is/are required by %s:"
-                       list=requirements.$dbsuffix
-                       pkgnamedb='requires obsolete'
-                       [ $COMMAND_SHOW_DEPTAG = none ] && \
-                               message_echo "WARNING: This command has no meaning with the current options setting." >&2
-                       database_query_for_each_matching_port "$grandtitle" "$title" "$list" "$pkgnamedb" \
-                               "$COMMAND_SHOW_DEPTAG" "$COMMAND_SHOW_LEVEL" "$@"
-                       ;;
-               initdependents)
-                       grandtitle="Dependencies based on the initially installed packages"
-                       title="The following port(s) depended on %s:"
-                       list=dependents.$dbsuffix
-                       pkgnamedb='initial'
-                       [ $COMMAND_SHOW_DEPTAG = none ] && \
-                               message_echo "WARNING: This command has no meaning with the current options setting." >&2
-                       database_query_for_each_matching_port "$grandtitle" "$title" "$list" "$pkgnamedb" \
-                               "$COMMAND_SHOW_DEPTAG" "$COMMAND_SHOW_LEVEL" "$@"
-                       ;;
-               dependents)
-                       grandtitle="Dependencies based on the latest ports tree"
-                       title="The following port(s) depend(s) on %s:"
-                       list=dependents.$dbsuffix
-                       pkgnamedb='requires obsolete'
-                       [ $COMMAND_SHOW_DEPTAG = none ] && \
-                               message_echo "WARNING: This command has no meaning with the current options setting." >&2
-                       database_query_for_each_matching_port "$grandtitle" "$title" "$list" "$pkgnamedb" \
-                               "$COMMAND_SHOW_DEPTAG" "$COMMAND_SHOW_LEVEL" "$@"
-                       ;;
-               status)
-                       grandtitle="Success/failure status in (re)installation"
-                       lists='todo|done|redo|resolved|failure|taboo|need|noneed|deleted|restored|conflict'
-                       database_query_for_list_inclusion_of_matching_port "$grandtitle" "$lists" "$pkgnamedb" \
-                               "$COMMAND_SHOW_DEPTAG" "$COMMAND_SHOW_LEVEL" "$@"
-                       ;;
-               esac
-               exit
-               ;;
-       esac
 }
 
-# ============= Execute command operations which must be done before building the temporary database =============
-command_exec_before_building_tempdb ()
+# ============= Execute command operations which must be done before the main process =============
+command_all_exec_before_main ()
 {
-       case $COMMAND_MODE in
-       redo)
-               program_deregister_stage_complete REDO_INIT
-               if [ $opt_reset_targets = yes ]
-               then
-                       program_deregister_stage_complete DETERMINE_SPECIFIED_TARGETS
-                       program_deregister_stage_complete INSPECT_ALL_DEPENDENCIES
-                       rm -rf "${DBDIR}/targets"
-               fi
-               ;;
-       esac
-       program_deregister_stage_complete FORGET::PREPARATION_INSPECT_MASTER
 }
 
-# ============= Execute command operations which must be done before actual (re/de)installation processes =============
-command_exec_before_actual_re_de_installation ()
+# ============= Execute command operations as the main process =============
+command_all_exec_main ()
 {
-       local tmp_msg
-       case $COMMAND_MODE in
-       do|redo)
-               case $COMMAND_DO_MODE in
-               prepare)
-                       tmp_msg=${TMPDIR}/command_exec_before_actual_re_de_installation:msg
-                       cat > "$tmp_msg" << eof
-Done (skipped reinstallation) at `message_timestamp`
-
- You can restart this process from the aborted/terminated point by executing without options or arguments as:
-  ${APPNAME}
-eof
-                       message_cat "$tmp_msg"
-                       temp_terminate_process ()
-                       {
-                       }
-                       exit
-                       ;;
-               esac
-               ;;
-       esac
 }
diff --git a/lib/libcommand_do.sh b/lib/libcommand_do.sh
new file mode 100644 (file)
index 0000000..8924600
--- /dev/null
@@ -0,0 +1,1439 @@
+#!/bin/sh -e
+# ==============================================================================
+# portsreinstall library script
+# - "do"/"redo" command operation -
+# Copyright (C) 2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# This software is distributed under the 2-Clause BSD License.
+# ==============================================================================
+
+# ============= Operation of redo command before the database reconstruction =============
+command_do_do__command_all_exec_before_build_database ()
+{
+       program_deregister_stage_complete FORGET::PREPARATION_INSPECT_MASTER
+       program_deregister_stage_complete ALL_COMPLETE
+}
+
+# ============= Operation of redo command before the database reconstruction =============
+command_do_redo__command_all_exec_before_build_database ()
+{
+       program_deregister_stage_complete REDO_INIT
+       if [ $opt_reset_targets = yes ]
+       then
+               program_deregister_stage_complete DETERMINE_SPECIFIED_TARGETS
+               program_deregister_stage_complete INSPECT_ALL_DEPENDENCIES
+               rm -rf "${DBDIR}/targets"
+       fi
+       command_do_do__command_all_exec_before_build_database
+}
+
+# ============= Meta process for redo =============
+command_do_meta_process_for_redo ()
+{
+       local PROGRAM_DEPENDS
+       PROGRAM_DEPENDS=''
+       _program_exec_and_record_completion__operation ()
+       {
+               rm -f "${DBDIR}/new_success_in_current_run"
+               [ "x$COMMAND_MODE" = xredo ] || return 0
+               message_echo "[REDO mode]"
+               message_echo
+       }
+       program_exec_and_record_completion REDO_INIT
+}
+
+# ============= Determine specified targets =============
+command_do_determin_specified_targets ()
+{
+       local PROGRAM_DEPENDS
+       PROGRAM_DEPENDS=''
+       _program_exec_and_record_completion__operation ()
+       {
+               local tag level dbsuffix
+               message_section_title "Determining specified targets"
+               cat "${DBDIR}/stage.loop_list/target_itself.specified" \
+                       "${DBDIR}/stage.loop_list/target_dependents.specified" \
+                       "${DBDIR}/stage.loop_list/target_requirements.specified" \
+                       "${DBDIR}/need.list" \
+                       "${DBDIR}/targets_specified_so_far" 2> /dev/null \
+                       | sort -u > ${DBDIR}/targets_specified_so_far.tmp
+               mv "${DBDIR}/targets_specified_so_far.tmp" "${DBDIR}/targets_specified_so_far"
+               rm -f "${DBDIR}/stage.loop_list/target_itself.specified" \
+                       "${DBDIR}/stage.loop_list/target_dependents.specified" \
+                       "${DBDIR}/stage.loop_list/target_requirements.specified"
+               if [ -n "$opt_target_itself$opt_target_dependents$opt_target_requirements" ]
+               then
+                       options_select_new_ports_if_duplicated O \
+                               "${DBDIR}/stage.loop_list/target_itself.specified" "$opt_target_itself"
+                       options_select_new_ports_if_duplicated t \
+                               "${DBDIR}/stage.loop_list/target_dependents.specified" "$opt_target_dependents"
+                       options_select_new_ports_if_duplicated T \
+                               "${DBDIR}/stage.loop_list/target_requirements.specified" "$opt_target_requirements"
+                       if [ `cat "${DBDIR}/stage.loop_list/target_itself.specified" \
+                               "${DBDIR}/stage.loop_list/target_dependents.specified" \
+                               "${DBDIR}/stage.loop_list/target_requirements.specified" | wc -l` -eq 0 ]
+                       then
+                               message_echo "ERROR: No matching port for target globs." >&2
+                               message_echo >&2
+                               exit 1
+                       fi
+                       cat "${DBDIR}/stage.loop_list/target_itself.specified" \
+                               "${DBDIR}/stage.loop_list/target_dependents.specified" \
+                               "${DBDIR}/stage.loop_list/target_requirements.specified" \
+                               | sort -u > ${TMPDIR}/DETERMINE_SPECIFIED_TARGETS.reset
+                       cat "${TMPDIR}/DETERMINE_SPECIFIED_TARGETS.reset" "${DBDIR}/need.list" 2> /dev/null \
+                               | sort -u > ${DBDIR}/need.list.tmp
+                       mv "${DBDIR}/need.list.tmp" "${DBDIR}/need.list"
+                       sort -u "${DBDIR}/need.list" "${DBDIR}/targets_specified_so_far" \
+                               > ${DBDIR}/targets_specified_so_far.tmp
+                       mv "${DBDIR}/targets_specified_so_far.tmp" "${DBDIR}/targets_specified_so_far"
+                       for tag in all run build none
+                       do
+                               for level in direct full
+                               do
+                                       dbsuffix=$tag.$level
+                                       {
+                                               cat "${TMPDIR}/DETERMINE_SPECIFIED_TARGETS.reset"
+                                               cat "${DBDIR}/stage.loop_list/target_dependents.specified" | while read origin
+                                               do
+                                                       nodedir=${DBDIR}/requires/$origin
+                                                       cat "$nodedir/dependents.$dbsuffix" 2> /dev/null
+                                               done
+                                               cat "${DBDIR}/stage.loop_list/target_requirements.specified" | while read origin
+                                               do
+                                                       nodedir=${DBDIR}/requires/$origin
+                                                       cat "$nodedir/requirements.$dbsuffix" 2> /dev/null
+                                               done
+                                       } | sort -u | while read origin
+                                       do
+                                               fileedit_rm_a_line "$origin" "${DBDIR}/success.$dbsuffix.list"
+                                               fileedit_rm_a_line "$origin" "${DBDIR}/todo_after_requirements_succeed.$dbsuffix.list"
+                                               rm -f "${DBDIR}/requires/$origin/succeeded_once"
+                                       done
+                               done
+                       done
+               fi
+               message_echo
+       }
+       program_exec_and_record_completion DETERMINE_SPECIFIED_TARGETS
+}
+
+# ============= Show specified targets =============
+command_do_show_specified_targets ()
+{
+       if [ -n "$opt_target_itself$opt_target_dependents$opt_target_requirements" -a $opt_batch_mode = no ]
+       then
+               message_echo "INFO: (Re/de-)installation will be carried out only for the targets:"
+               echo
+               if [ `wc -l < ${DBDIR}/stage.loop_list/target_itself.specified` -gt 0 ]
+               then
+                       message_echo "[Targets only]"
+                       echo "----------------------------------------"
+                       cat "${DBDIR}/stage.loop_list/target_itself.specified"
+                       echo "----------------------------------------"
+                       echo
+               fi
+               if [ `wc -l < ${DBDIR}/stage.loop_list/target_dependents.specified` -gt 0 ]
+               then
+                       message_echo "[Targets with their `options_get_dependency_msgterm` dependents]"
+                       echo "----------------------------------------"
+                       cat "${DBDIR}/stage.loop_list/target_dependents.specified"
+                       echo "----------------------------------------"
+                       echo
+               fi
+               if [ `wc -l < ${DBDIR}/stage.loop_list/target_requirements.specified` -gt 0 ]
+               then
+                       message_echo "[Targets with their `options_get_dependency_msgterm` requirements]"
+                       echo "----------------------------------------"
+                       cat "${DBDIR}/stage.loop_list/target_requirements.specified"
+                       echo "----------------------------------------"
+                       echo
+               fi
+       fi
+}
+
+# ============= Determine all target ports =============
+command_do_determine_all_target_ports ()
+{
+       local PROGRAM_DEPENDS
+       PROGRAM_DEPENDS='DETERMINE_SPECIFIED_TARGETS COLLECT_ALL_INSTALLED_PACKAGES'
+       _program_exec_and_record_completion__operation ()
+       {
+               message_section_title "Determining all target ports"
+               {
+                       if [ $opt_only_target_scope = no ]
+                       then
+                               cat "${DBDIR}/installed_ports" 2> /dev/null || :
+                       fi
+                       cat "${DBDIR}/stage.loop_list/target_itself.specified" || :
+                       cat "${DBDIR}/stage.loop_list/target_dependents.specified" || :
+                       cat "${DBDIR}/stage.loop_list/target_requirements.specified" || :
+                       cat "${DBDIR}/targets_specified_so_far" || :
+               }  2> /dev/null | sort -u > "${DBDIR}/stage.loop_list/ports_to_inspect"
+               cp /dev/null "${DBDIR}/done_required_ports_to_inspect"
+               message_echo
+       }
+       program_exec_and_record_completion DETERMINE_ALL_TARGET_PORTS
+}
+
+# ============= Check ports of which the port options are changed and reset their databases =============
+# Return status 0 for no need to update of inspected ports and 1 for needed to do it
+command_do_reset_changed_portdb ()
+{
+       local tmp_ls
+       program_chk_stage_complete INSPECT_DEPENDENTS || return
+       pkgsys_exists_saved_port_oprions_timestamps || return
+       message_section_title "Inspecting changes of port options"
+       tmp_ls=${TMPDIR}/command_do_reset_changed_portdb
+       rm -f "$tmp_ls.updated"
+       if [ ! -d "${PORT_DBDIR}" ]
+       then
+               message_echo "WARNING: ${PORT_DBDIR} is missing. All port options are recognized as default."
+       fi
+       pkgsys_get_saved_port_oprions_timestamps_all > $tmp_ls.db
+       pkgsys_get_current_port_oprions_timestamp > $tmp_ls.log
+       pkgsys_get_changed_port_oprions "$tmp_ls.db" "$tmp_ls.log" > $tmp_ls.diff
+       if ! [ `wc -l < $tmp_ls.diff` -gt 0 ]
+       then
+               message_echo
+               return
+       fi
+       message_echo "INFO: There are some changes. Inspecting the detail..."
+       cp /dev/null "$tmp_ls.uninspected.dbfile"
+       cp /dev/null "$tmp_ls.uninspected.origin"
+       cp /dev/null "$tmp_ls.nonexistent.db"
+       pkgsys_conv_portorigins_to_portoptiondbs < $tmp_ls.diff > $tmp_ls.glob
+       str_escape_replaceval_filter < $tmp_ls.diff > $tmp_ls.diff.rpl
+       paste "$tmp_ls.diff" "$tmp_ls.diff.rpl" "$tmp_ls.glob" | while read -r dbfile dbfile_rpl glob
+       do
+               pkgsys_eval_ports_glob "$glob" > $tmp_ls.origins
+               if [ `wc -l < $tmp_ls.origins` -gt 0 ]
+               then
+                       sed -E "s/^/$dbfile_rpl /" < $tmp_ls.origins
+               else
+                       echo $dbfile >> $tmp_ls.nonexistent.db
+               fi
+       done | while read dbfile origin
+       do
+               if [ -d "${DBDIR}/requires/$origin" ]
+               then
+                       message_echo "Change detected on $origin: Resetting"
+                       database_build_patch_reconf "$origin"
+                       program_deregister_stage_complete INSPECT_ALL_DEPENDENCIES
+                       program_deregister_stage_complete ALL_COMPLETE
+                       touch "$tmp_ls.updated"
+               else
+                       echo "$dbfile" >> $tmp_ls.uninspected.dbfile
+                       echo "$origin" >> $tmp_ls.uninspected.origin
+               fi
+       done
+       message_echo "INFO: Recording for not inspected ports..."
+       pkgsys_conv_portorigin_to_port_oprion_timestamp_logname < $tmp_ls.uninspected.origin > $tmp_ls.uninspected.logname
+       str_escape_regexp_filter < $tmp_ls.uninspected.dbfile | sed 's/^/^/;s/$/[[:space:]]/' > $tmp_ls.uninspected.dbfile_ptn
+       paste "$tmp_ls.uninspected.dbfile_ptn" "$tmp_ls.uninspected.logname" | while read -r dbfile_ptn logname
+       do
+               grep -E "$dbfile_ptn" < $tmp_ls.log > ${DBDIR}/ls_dbdir/$logname.log 2> /dev/null || :
+       done
+       str_escape_regexp_filter < $tmp_ls.nonexistent.db | sed 's/^/^/;s/$/[[:space:]]/' > $tmp_ls.nonexistent.db_ptn
+       grep -E -f "$tmp_ls.nonexistent.db_ptn" < $tmp_ls.log | pkgsys_register_list_nonexistent_portopriondb
+       message_echo
+       [ ! -e "$tmp_ls.updated" ]
+}
+
+# ============= Inspection of all dependencies =============
+command_do_inspection_of_all_dependencies ()
+{
+       local PROGRAM_DEPENDS
+       PROGRAM_DEPENDS='PARSE_CONF DETERMINE_ALL_TARGET_PORTS'
+       _program_exec_restartable_loop_operation__routine ()
+       {
+               local origin
+               origin=$1
+               database_build_inspect_dependencies "$origin"
+       }
+       _program_exec_and_record_completion__operation ()
+       {
+               local DEPTH_INDEX 
+               message_section_title "Inspecting dependencies of the all installed packages"
+               [ $opt_only_target_scope = no -a -n "$opt_target_itself$opt_target_dependents$opt_target_requirements" ] && \
+                       message_echo "INFO: Ports which seem irrelevant to the targets are also inspected in order to get complete information."
+               DEPTH_INDEX='--'
+               program_exec_restartable_loop_operation ports_to_inspect
+               database_build_post_inspect_dependencies
+               database_maintain_clear_prevset
+               message_echo
+       }
+       program_exec_and_record_completion INSPECT_ALL_DEPENDENCIES
+}
+
+# ============= Convert dependency-lists to actual ones =============
+command_do_convert_dependency_lists_to_actual_ones ()
+{
+       local PROGRAM_DEPENDS
+       PROGRAM_DEPENDS='INSPECT_ALL_DEPENDENCIES'
+       _program_exec_restartable_loop_operation__routine ()
+       {
+               local origin table dbtag level tag target
+               origin=$1
+               for table in dependents requirements
+               do
+                       for dbtag in requires obsolete
+                       do
+                               for level in direct full
+                               do
+                                       for tag in all run build
+                                       do
+                                               target=${DBDIR}/$dbtag/$origin/${table}.${tag}.${level}
+                                               if [ -e "$target.src" ]
+                                               then
+                                                       sed -E -f "${DBDIR}/REPLACE.complete_sed_pattern" "$target.src" \
+                                                               | grep -v '^$' | sort -u > $target.tmp
+                                                       [ -e "$target" ] && ! diff -q "$target.tmp" "$target" > /dev/null \
+                                                               && echo "$origin" >> ${DBDIR}/update_dependencies
+                                                       mv "$target.tmp" "$target"
+                                               else
+                                                       [ -e "$target" ] && echo "$origin" >> ${DBDIR}/update_dependencies
+                                                       rm -f "$target"
+                                               fi
+                                       done
+                               done
+                       done
+               done
+       }
+       _program_exec_and_record_completion__operation ()
+       {
+               message_section_title "Conversion of dependency-lists to actual ones"
+               program_exec_restartable_loop_operation convert_dependency_lists
+               sort -u "${DBDIR}/update_dependencies" > ${DBDIR}/update_dependencies.tmp
+               mv "${DBDIR}/update_dependencies.tmp" "${DBDIR}/update_dependencies"
+               for tag in all run build
+               do
+                       ( cd "${DBDIR}/requires" && \
+                               find . -depth 3 -type f -name requirements.${tag}.full -or -name requirements.${tag}.full.orig ) \
+                               | sort -u \
+                               | sed 's|^./||;s|/[^/]*$||' \
+                               | grep -v -Fx -f "${DBDIR}/update_dependencies" \
+                               > ${TMPDIR}/convert_requirements_list:full_complete.grep_pattern || :
+                       ( cd "${DBDIR}/requires" && \
+                               find . -depth 3 -type f -name requirements.${tag}.direct -or -name requirements.${tag}.direct.orig ) \
+                               | sort -u \
+                               | sed 's|^./||;s|/[^/]*$||' \
+                               | grep -v -Fx -f "${TMPDIR}/convert_requirements_list:full_complete.grep_pattern" \
+                               > ${DBDIR}/stage.loop_list/complete_recursive_${tag}time_reqlists || :
+               done
+               for inspected_level_tmp in direct node
+               do
+                       cat "${DBDIR}/ports.inspected.${inspected_level_tmp}.list" || :
+               done 2> /dev/null | sort -u > ${DBDIR}/stage.loop_list/trim_dependency_lists_rm_uninspected_ports
+               find "${DBDIR}/requires" -depth 2 -type d > ${DBDIR}/stage.loop_list/inspect_dependent
+               [ -e "${DBDIR}/dependents_files" ] && \
+                       mv "${DBDIR}/dependents_files" "${DBDIR}/dependents_files.prev"
+               rm -f "${DBDIR}/stage.loop_list/make_dependents_lists_unique.tmp" "${DBDIR}/dependents_files.tmp"
+               message_echo
+       }
+       program_exec_and_record_completion CONVERT_REQUIREMENTS_LIST
+}
+
+# ============= Completion of recursive requirement lists =============
+command_do_completion_of_recursive_requirement_lists ()
+{
+       local PROGRAM_DEPENDS _REQUIREMENT_LISTS_tag
+       for _REQUIREMENT_LISTS_tag in all run build
+       do
+               PROGRAM_DEPENDS='CONVERT_REQUIREMENTS_LIST'
+               _program_exec_restartable_loop_operation__routine ()
+               {
+                       local tag dbpath origin suffix
+                       tag=${_REQUIREMENT_LISTS_tag}
+                       dbpath=$1
+                       origin=`str_dirpath_to_origin "$dbpath"`
+                       for suffix in '' .orig
+                       do
+                               database_build_get_complete_recursive_dependency "$tag" "$origin" "$suffix" > /dev/null
+                       done
+               }
+               _program_exec_and_record_completion__operation ()
+               {
+                       local tag
+                       tag=${_REQUIREMENT_LISTS_tag}
+                       message_section_title "Completion of ${tag}-time requirement lists"
+                       program_exec_restartable_loop_operation complete_recursive_${tag}time_reqlists
+                       message_echo
+               }
+               program_exec_and_record_completion RECURSIVE_REQUIREMENT_LISTS:${_REQUIREMENT_LISTS_tag}
+       done
+}
+
+# ============= Trim dependency lists by removing uninspected ports =============
+command_do_trim_dependency_lists_by_removing_uninspected_ports ()
+{
+       local PROGRAM_DEPENDS
+       if [ $opt_only_target_scope = yes ]
+       then
+               PROGRAM_DEPENDS='INSPECT_ALL_DEPENDENCIES CONVERT_REQUIREMENTS_LIST'
+               _program_exec_restartable_loop_operation__routine ()
+               {
+                       local dbpath tag level srcdb
+                       dbpath=$1
+                       for tag in all run build
+                       do
+                               for level in direct full
+                               do
+                                       srcdb=requirements.${tag}.${level}
+                                       [ -e "$dbpath/$srcdb" ] || continue
+                                       grep -Fx -f "${DBDIR}/inspected_ports" "$dbpath/$srcdb" > $dbpath/$srcdb.tmp || :
+                                       mv "$dbpath/$srcdb.tmp" "$dbpath/$srcdb"
+                               done
+                       done
+               }
+               _program_exec_and_record_completion__operation ()
+               {
+                       message_section_title "Trimming dependency lists by removing uninspected ports"
+                       program_exec_restartable_loop_operation trim_dependency_lists_rm_uninspected_ports
+                       message_echo
+               }
+               program_exec_and_record_completion TRIM_DEPENDENCY_LISTS_RM_UNINSPECTED_PORTS
+       fi
+}
+
+# ============= Inspection of dependents =============
+command_do_inspection_of_dependents ()
+{
+       local PROGRAM_DEPENDS
+       PROGRAM_DEPENDS='INSPECT_ALL_DEPENDENCIES CONVERT_REQUIREMENTS_LIST TRIM_DEPENDENCY_LISTS_RM_UNINSPECTED_PORTS'
+       _program_exec_restartable_loop_operation__routine ()
+       {
+               local dbpath origin tag level suffix srcdb dstdb
+               dbpath=$1
+               origin=`str_dirpath_to_origin "$dbpath"`
+               for tag in all run build
+               do
+                       for suffix in '' .orig
+                       do
+                               for level in direct full
+                               do
+                                       srcdb=requirements.${tag}.${level}${suffix}
+                                       [ -e "$dbpath/$srcdb" ] || continue
+                                       dstdb=dependents.${tag}.${level}${suffix}
+                                       while read origin_requirement
+                                       do
+                                               dstpath=${DBDIR}/requires/$origin_requirement
+                                               echo "$dstpath/$dstdb" >> ${DBDIR}/dependents_files.tmp
+                                               [ "$dstpath/$dstdb" -nt "$dbpath/$srcdb" ] && continue
+                                               mkdir -p "$dstpath"
+                                               echo "$origin" >> $dstpath/$dstdb.raw
+                                               echo "$dstpath/$dstdb" >> ${DBDIR}/stage.loop_list/make_dependents_lists_unique.tmp
+                                       done < $dbpath/$srcdb
+                               done
+                               srcdb=ignored_requirements.${tag}${suffix}
+                               [ -e "$dbpath/$srcdb" ] || continue
+                               dstdb=ignored_dependents.${tag}${suffix}
+                               while read origin_requirement
+                               do
+                                       dstpath=${DBDIR}/requires/$origin_requirement
+                                       echo "$dstpath/$dstdb" >> ${DBDIR}/ignored_dependents_files.tmp
+                                       [ "$dstpath/$dstdb" -nt "$dbpath/$srcdb" ] && continue
+                                       mkdir -p "$dstpath"
+                                       echo "$origin" >> $dstpath/$dstdb.raw
+                                       echo "$dstpath/$dstdb" >> ${DBDIR}/stage.loop_list/make_ignored_dependents_lists_unique.tmp
+                               done < $dbpath/$srcdb
+                       done
+               done
+       }
+       _program_exec_and_record_completion__operation ()
+       {
+               local dbrequires_valesc
+               message_section_title "Inspection of dependents"
+               dbrequires_valesc=`str_escape_replaceval "${DBDIR}/requires/"`
+               program_exec_restartable_loop_operation inspect_dependent
+               for dbtype in dependents ignored_dependents
+               do
+                       sort -u "${DBDIR}/stage.loop_list/make_${dbtype}_lists_unique.tmp" 2> /dev/null \
+                               > ${DBDIR}/stage.loop_list/make_${dbtype}_lists_unique || :
+                       sort -u "${DBDIR}/${dbtype}_files.tmp" 2> /dev/null > ${DBDIR}/${dbtype}_files || :
+                       [ -e "${DBDIR}/make_${dbtype}_lists_unique.prev" ] && \
+                               fileedit_manipulate_old_lines "${DBDIR}/${dbtype}_files.prev" "${DBDIR}/${dbtype}_files" \
+                               | xargs rm -f
+               done
+               message_echo
+       }
+       program_exec_and_record_completion INSPECT_DEPENDENTS
+}
+
+# ============= Remove duplicated lines in dependents lists =============
+command_do_remove_duplicated_lines_in_dependents_lists ()
+{
+       local PROGRAM_DEPENDS
+       PROGRAM_DEPENDS='CONVERT_REQUIREMENTS_LIST INSPECT_DEPENDENTS'
+       _program_exec_restartable_loop_operation__routine ()
+       {
+               local dbpath tag level dstdb
+               dstdb=$1
+               cat "$dstdb" "$dstdb.raw" 2> /dev/null | sort -u > $dstdb.tmp
+               mv "$dstdb.tmp" "$dstdb"
+               rm -f "$dstdb.raw"
+       }
+       _program_exec_and_record_completion__operation ()
+       {
+               local dbrequires_valesc
+               message_section_title "Removing duplicated items in dependents lists"
+               program_exec_restartable_loop_operation make_dependents_lists_unique
+               message_echo
+       }
+       program_exec_and_record_completion MAKE_DEPENDENTS_LISTS_UNIQUE
+}
+
+# ============= Remove duplicated lines in ignored dependents lists =============
+command_do_remove_duplicated_lines_in_ignored_dependents_lists ()
+{
+       local PROGRAM_DEPENDS
+       PROGRAM_DEPENDS='CONVERT_REQUIREMENTS_LIST INSPECT_DEPENDENTS'
+       _program_exec_restartable_loop_operation__routine ()
+       {
+               local dbpath tag level dstdb
+               dstdb=$1
+               cat "$dstdb" "$dstdb.raw" 2> /dev/null | sort -u > $dstdb.tmp
+               mv "$dstdb.tmp" "$dstdb"
+               rm -f "$dstdb.raw"
+       }
+       _program_exec_and_record_completion__operation ()
+       {
+               local dbrequires_valesc
+               message_section_title "Removing duplicated items in ignored dependents lists"
+               program_exec_restartable_loop_operation make_ignored_dependents_lists_unique
+               message_echo
+       }
+       program_exec_and_record_completion MAKE_IGNORED_DEPENDENTS_LISTS_UNIQUE
+}
+
+# ============= Preparation of target attribute information =============
+command_do_preparation_of_target_attribute_information ()
+{
+       local PROGRAM_DEPENDS _TARGET_ATTR_INFO_table
+       for _TARGET_ATTR_INFO_table in requirements dependents itself
+       do
+               [ `cat "${DBDIR}/stage.loop_list/target_${_TARGET_ATTR_INFO_table}.replaced.specified" 2> /dev/null \
+                       | wc -l` -gt 0 ] || continue
+               PROGRAM_DEPENDS='DETERMINE_SPECIFIED_TARGETS CONVERT_REQUIREMENTS_LIST'
+               _program_exec_restartable_loop_operation__routine ()
+               {
+                       local origin dbtargets_valesc table
+                       origin=$1
+                       dbtargets_valesc=`str_escape_replaceval "${DBDIR}/targets/"`
+                       table=${_TARGET_ATTR_INFO_table}
+                       for database in requires initial
+                       do
+                               dbpath=${DBDIR}/$database/$origin
+                               dstpath=${DBDIR}/targets/$origin
+                               mkdir -p "$dstpath"
+                               touch "$dstpath/target_itself"
+                               echo "$origin" >> ${DBDIR}/all_targets.lst
+                               [ $table = itself ] && continue
+                               for tag in all run build
+                               do
+                                       for level in direct full
+                                       do
+                                               srcdb=${table}.${tag}.${level}
+                                               dstdb=target_${database}_${table}.${tag}.${level}
+                                               [ -e "$dbpath/$srcdb" ] || continue
+                                               cat "$dbpath/$srcdb" >> ${DBDIR}/all_targets.lst
+                                               sed -E "s/^/$dbtargets_valesc/; s|$|/$dstdb|" "$dbpath/$srcdb" \
+                                                       | fileedit_add_a_line_to_files_if_new "$origin"
+                                       done
+                               done
+                       done
+               }
+               _program_exec_and_record_completion__operation ()
+               {
+                       local table
+                       table=${_TARGET_ATTR_INFO_table}
+                       message_section_title "Preparation of target attribute information for dependency [$table]"
+                       program_exec_restartable_loop_operation target_$table.replaced.specified
+                       message_echo
+               }
+               program_exec_and_record_completion TARGET_ATTR_INFO:${_TARGET_ATTR_INFO_table}
+       done
+}
+
+# ============= Post-process after the preparation of target attribute information =============
+command_do_post_process_after_the_preparation_of_target_attribute_information ()
+{
+       local PROGRAM_DEPENDS
+       PROGRAM_DEPENDS='MAKE_DEPENDENTS_LISTS_UNIQUE MAKE_IGNORED_DEPENDENTS_LISTS_UNIQUE TARGET_ATTR_INFO:requirements TARGET_ATTR_INFO:dependents'
+       _program_exec_and_record_completion__operation ()
+       {
+               message_section_title "Post-process after the preparation of target attribute information"
+               sort -u "${DBDIR}/all_targets.lst" 2> /dev/null \
+                       | grep -Fx -f "${DBDIR}/inspected_ports" \
+                       | sed -E -f "${DBDIR}/REPLACE.complete_sed_pattern" 2> /dev/null \
+                       > ${DBDIR}/all_targets.lst.tmp || :
+               mv "${DBDIR}/all_targets.lst.tmp" "${DBDIR}/all_targets.lst"
+               find "${DBDIR}/targets" -depth 2 -type d > ${DBDIR}/stage.loop_list/build_complement_to_new_dependents_for_targets 2> /dev/null || :
+               {
+                       cat "${DBDIR}/all_targets.lst" "${DBDIR}/need.with_replaced.list" 2> /dev/null || :
+                       find "${DBDIR}/moved_from" -depth 3 -type f -name installed_version \
+                               | sed -E 's|.*/([^/]+/[^/]+)/[^/]*$|\1|'
+               } | sort -u > ${DBDIR}/stage.loop_list/inspect_necessity
+               cp /dev/null "${DBDIR}/stage.loop_list/parse_target_attr_info"
+               find -E "${DBDIR}/requires" -depth 3 -type f -regex '.*/necessary_port\.(direct|full)$' -delete
+               message_echo
+       }
+       program_exec_and_record_completion TARGET_ATTR_INFO_POSTPROCESS
+}
+
+# ============= Build of data on complement to new dependents for target attribute information =============
+command_do_build_of_data_on_complement_to_new_dependents_for_target_attribute_information ()
+{
+       local PROGRAM_DEPENDS
+       PROGRAM_DEPENDS='TARGET_ATTR_INFO_POSTPROCESS TARGET_ATTR_INFO:requirements TARGET_ATTR_INFO:dependents CONVERT_REQUIREMENTS_LIST'
+       _program_exec_restartable_loop_operation__routine ()
+       {
+               local dbpath origin
+               dbpath=$1
+               origin=`str_dirpath_to_origin "$dbpath"`
+               database_build_complement_to_new_dependents_for_targets "$origin"
+       }
+       _program_exec_and_record_completion__operation ()
+       {
+               message_section_title "Build of data on complement to new dependents for target attribute information"
+               program_exec_restartable_loop_operation build_complement_to_new_dependents_for_targets
+               sort -u "${DBDIR}/stage.loop_list/parse_target_attr_info" > ${DBDIR}/stage.loop_list/parse_target_attr_info.tmp
+               mv "${DBDIR}/stage.loop_list/parse_target_attr_info.tmp" "${DBDIR}/stage.loop_list/parse_target_attr_info"
+               message_echo
+       }
+       program_exec_and_record_completion COMPLEMENT_TO_NEW_DEPENDENTS_FOR_TARGET_ATTR_INFO
+}
+
+# ============= Parse target attribute information =============
+command_do_parse_target_attribute_information ()
+{
+       local PROGRAM_DEPENDS
+       PROGRAM_DEPENDS='COMPLEMENT_TO_NEW_DEPENDENTS_FOR_TARGET_ATTR_INFO'
+       _program_exec_restartable_loop_operation__routine ()
+       {
+               local dbpath origin
+               dbpath=$1
+               origin=`str_dirpath_to_origin "$dbpath"`
+               database_build_target_attributes "$origin"
+       }
+       _program_exec_and_record_completion__operation ()
+       {
+               message_section_title "Parsing target attribute information"
+               program_exec_restartable_loop_operation parse_target_attr_info
+               message_echo
+       }
+       program_exec_and_record_completion PARSE_TARGET_ATTR_INFO
+}
+
+# ============= Inspection of necessity =============
+command_do_inspection_of_necessity ()
+{
+       local PROGRAM_DEPENDS
+       PROGRAM_DEPENDS='TARGET_ATTR_INFO_POSTPROCESS RECURSIVE_REQUIREMENT_LISTS:run RECURSIVE_REQUIREMENT_LISTS:build INSPECT_ALL_DEPENDENCIES'
+       _program_exec_restartable_loop_operation__routine ()
+       {
+               local origin
+               origin=$1
+               for level in direct full
+               do
+                       database_build_inspect_necessity_for_only_new_upgrade "$origin" "$level"
+               done
+       }
+       _program_exec_and_record_completion__operation ()
+       {
+               message_section_title "Inspection of necessity"
+               program_exec_restartable_loop_operation inspect_necessity
+               for level in direct full
+               do
+                       find "${DBDIR}/requires" -depth 3 -type f -name "necessary_port.${level}" \
+                               > ${DBDIR}/stage.loop_list/necessary_ports.${level}
+               done
+               message_echo
+       }
+       program_exec_and_record_completion INSPECT_NECESSITY
+}
+
+# ============= Inspection of necessary upgrades =============
+command_do_inspection_of_necessary_upgrades ()
+{
+       local PROGRAM_DEPENDS _NECESSARY_UPDATES_level
+       for _NECESSARY_UPDATES_level in direct full
+       do
+               PROGRAM_DEPENDS='INSPECT_NECESSITY INSPECT_ALL_DEPENDENCIES MAKE_DEPENDENTS_LISTS_UNIQUE MAKE_IGNORED_DEPENDENTS_LISTS_UNIQUE'
+               _program_exec_restartable_loop_operation__routine ()
+               {
+                       local markerpath level dbpath origin tag
+                       markerpath=$1
+                       level=${_NECESSARY_UPDATES_level}
+                       dbpath=`dirname "$markerpath"`
+                       origin=`str_dirpath_to_origin "$dbpath"`
+                       database_query_does_a_port_need_update "$origin" || return 0
+                       for tag in all run build none
+                       do
+                               touch "$dbpath/necessary_upgrade.$tag.${level}"
+                               [ -e "$dbpath/dependents.$tag.${level}" -o "$dbpath/ignored_dependents.$tag" ] || continue
+                               cat "$dbpath/dependents.$tag.${level}" "$dbpath/ignored_dependents.$tag" 2> /dev/null | \
+                                       while read origin_dependent
+                                       do
+                                               touch "${DBDIR}/requires/$origin_dependent/necessary_upgrade.$tag.${level}"
+                                       done
+                       done
+               }
+               _program_exec_and_record_completion__operation ()
+               {
+                       local level
+                       level=${_NECESSARY_UPDATES_level}
+                       message_section_title "Inspection of necessary upgrades at the $level level"
+                       program_exec_restartable_loop_operation necessary_ports.${level}
+                       message_echo
+               }
+               program_exec_and_record_completion NECESSARY_UPDATES:${_NECESSARY_UPDATES_level}
+       done
+}
+
+# ============= Preparation for inspection of new leaf ports =============
+command_do_preparation_for_inspection_of_new_leaf_ports ()
+{
+       local PROGRAM_DEPENDS
+       if [ ! -e "${DBDIR}/inspected_ports_only_partially" ]
+       then
+               PROGRAM_DEPENDS='INSPECT_ALL_DEPENDENCIES MAKE_DEPENDENTS_LISTS_UNIQUE MAKE_IGNORED_DEPENDENTS_LISTS_UNIQUE PARSE_CONF'
+               _program_exec_and_record_completion__operation ()
+               {
+                       message_section_title "Preparation for inspection of new leaf ports"
+                       find "${DBDIR}/requires" -depth 3 -type f -name dependents.all.full -or -name ignored_dependents.all \
+                               | sed -E 's|.*/([^/]+/[^/]+)/[^/]+$|\1|' \
+                               | sort -u > ${TMPDIR}/PREPARE_INSPECT_LEAF_PORTS:nonleaf_ports
+                       sort -u "${DBDIR}/inspected_ports" > ${TMPDIR}/PREPARE_INSPECT_LEAF_PORTS:inspected_ports
+                       fileedit_manipulate_new_lines \
+                               "${TMPDIR}/PREPARE_INSPECT_LEAF_PORTS:nonleaf_ports" \
+                               "${TMPDIR}/PREPARE_INSPECT_LEAF_PORTS:inspected_ports" \
+                               | grep -v -Fx -f "${DBDIR}/conf/HOLD:PORTS.parsed" 2> /dev/null \
+                               > ${DBDIR}/stage.loop_list/leaf_ports_primary_candidates || :
+                       cp /dev/null "${DBDIR}/leaf_ports.filter"
+                       cp /dev/null "${DBDIR}/stage.loop_list/leaf_ports_secondary_candidates"
+                       message_echo
+               }
+               program_exec_and_record_completion PREPARE_INSPECT_LEAF_PORTS
+       fi
+}
+
+# ============= Inspection of new primary leaf ports =============
+command_do_inspection_of_new_primary_leaf_ports ()
+{
+       local PROGRAM_DEPENDS
+       if [ ! -e "${DBDIR}/inspected_ports_only_partially" ]
+       then
+               PROGRAM_DEPENDS='INSPECT_ALL_DEPENDENCIES MAKE_DEPENDENTS_LISTS_UNIQUE MAKE_IGNORED_DEPENDENTS_LISTS_UNIQUE PREPARE_INSPECT_LEAF_PORTS PARSE_CONF'
+               _program_exec_restartable_loop_operation__routine ()
+               {
+                       local origin origin_ini dbpath origin_req
+                       origin=$1
+                       pkgsys_is_pkgtool "$origin" && return
+                       dbpath=${DBDIR}/requires/$origin
+                       grep -q -Fx "$origin" "${DBDIR}/need.with_replaced.list" 2> /dev/null && return
+                       if ! grep -q -Fx "$origin" "${DBDIR}/noneed.list" 2> /dev/null
+                       then
+                               if [ -e "$dbpath/initial_orig" ]
+                               then
+                                       origin_ini=`cat "$dbpath/initial_orig"`
+                                       [ -e "${DBDIR}/initial/$origin_ini/installed_version" \
+                                               -a `cat "${DBDIR}/initial/$origin_ini/dependents.all.full" 2> /dev/null | wc -l` -eq 0 ] \
+                                               && return
+                               fi
+                               [ -e "${DBDIR}/initial/$origin/installed_version" \
+                                       -a `cat "${DBDIR}/initial/$origin/dependents.all.full" 2> /dev/null | wc -l` -eq 0 ] \
+                                       && return
+                       fi
+                       if [ -e "$dbpath/requirements.all.full" -o -e "$dbpath/ignored_requirements.all" ]
+                       then
+                               cat "$dbpath/requirements.all.full" "$dbpath/ignored_requirements.all" 2> /dev/null | \
+                                       grep -v -Fx -f "${DBDIR}/conf/HOLD:PORTS.parsed" 2> /dev/null| \
+                                       fileedit_add_lines_if_new "${DBDIR}/stage.loop_list/leaf_ports_secondary_candidates" || :
+                       fi
+                       fileedit_add_a_line_if_new "$origin" "${DBDIR}/leaf_ports.filter"
+               }
+               _program_exec_and_record_completion__operation ()
+               {
+                       local num_leaves num_leaves_prev
+                       message_section_title "Inspection of new primary leaf ports"
+                       program_exec_restartable_loop_operation leaf_ports_primary_candidates
+                       wc -l < ${DBDIR}/leaf_ports.filter | tr -d ' ' > ${DBDIR}/num_leaves
+                       cp /dev/null "${DBDIR}/leaf_ports_secondary_candidates.new_requirements"
+                       message_echo "  `cat "${DBDIR}/num_leaves"` primary leaf port(s) is/are found."
+                       message_echo
+               }
+               program_exec_and_record_completion INSPECT_PRIMARY_LEAF_PORTS
+       fi
+}
+
+# ============= Inspection of requirements of new leaf ports =============
+command_do_inspection_of_requirements_of_new_leaf_ports ()
+{
+       local PROGRAM_DEPENDS
+       if [ ! -e "${DBDIR}/inspected_ports_only_partially" ]
+       then
+               PROGRAM_DEPENDS='INSPECT_ALL_DEPENDENCIES MAKE_DEPENDENTS_LISTS_UNIQUE MAKE_IGNORED_DEPENDENTS_LISTS_UNIQUE INSPECT_PRIMARY_LEAF_PORTS PARSE_CONF'
+               _program_exec_and_record_completion__operation ()
+               {
+                       local num_leaves num_leaves_prev num_inspect num_leaves_new
+                       message_section_title "Inspection of requirements of new leaf ports"
+                       message_echo "INFO: The inspection proceeds by iterative method."
+                       while :
+                       do
+                               _program_exec_restartable_loop_operation__routine ()
+                               {
+                                       local origin dbpath
+                                       origin=$1
+                                       pkgsys_is_pkgtool "$origin" && return
+                                       dbpath=${DBDIR}/requires/$origin
+                                       grep -q -Fx "$origin" "${DBDIR}/need.with_replaced.list" 2> /dev/null && return
+                                       cat "$dbpath/dependents.all.full" "$dbpath/ignored_dependents.all"  2> /dev/null \
+                                               | grep -Fxq -v -f "${DBDIR}/leaf_ports.filter" 2> /dev/null && return
+                                       cat "$dbpath/requirements.all.full" "$dbpath/ignored_requirements.all" 2> /dev/null \
+                                               >> ${DBDIR}/leaf_ports_secondary_candidates.new_requirements || :
+                                       fileedit_add_a_line_if_new "$origin" "${DBDIR}/leaf_ports.filter"
+                               }
+                               program_exec_restartable_loop_operation leaf_ports_secondary_candidates
+                               num_leaves_prev=`cat "${DBDIR}/num_leaves"`
+                               num_leaves=`wc -l < ${DBDIR}/leaf_ports.filter | tr -d ' '`
+                               num_leaves_new=`echo $(($num_leaves-$num_leaves_prev)) | tr -d ' '`
+                               if [ $num_leaves_new -eq 0 ]
+                               then
+                                       message_echo "  No more leaf port is found."
+                                       message_echo "  $num_leaves leaf port(s) is/are found in total."
+                                       break
+                               fi
+                               {
+                                       grep -Fx -v -f "${DBDIR}/leaf_ports.filter" \
+                                               "${DBDIR}/stage.loop_list/leaf_ports_secondary_candidates" || :
+                                       cat "${DBDIR}/leaf_ports_secondary_candidates.new_requirements" || :
+                               } 2> /dev/null | grep -v -Fx -f "${DBDIR}/conf/HOLD:PORTS.parsed" 2> /dev/null | sort -u \
+                                       > ${DBDIR}/stage.loop_list/leaf_ports_secondary_candidates.tmp || :
+                               program_reset_loop_for_stage INSPECT_REQUIREMENTS_OF_LEAF_PORTS
+                               mv "${DBDIR}/stage.loop_list/leaf_ports_secondary_candidates.tmp" \
+                                       "${DBDIR}/stage.loop_list/leaf_ports_secondary_candidates"
+                               cp /dev/null "${DBDIR}/leaf_ports_secondary_candidates.new_requirements"
+                               echo "$num_leaves" > ${DBDIR}/num_leaves
+                               num_inspect=`wc -l < ${DBDIR}/stage.loop_list/leaf_ports_secondary_candidates | tr -d ' '`
+                               message_echo "  $num_leaves_new leaf port(s) is/are newly found; continue for $num_inspect candidate(s)."
+                       done
+                       grep -Fx -f "${DBDIR}/leaf_ports.filter" "${DBDIR}/inspected_ports" 2> /dev/null | sort -u > ${DBDIR}/leaf_ports || :
+                       message_echo
+               }
+               program_exec_and_record_completion INSPECT_REQUIREMENTS_OF_LEAF_PORTS
+       fi
+}
+
+# ============= Order the ports considering dependencies =============
+command_do_order_the_ports_considering_dependencies ()
+{
+       local PROGRAM_DEPENDS
+       PROGRAM_DEPENDS='CONVERT_REQUIREMENTS_LIST'
+       _program_exec_and_record_completion__operation ()
+       {
+               message_section_title "Ordering dependencies"
+               if ! database_build_order_ports_considering_dependencies
+               then
+                       message_echo "ERROR: Unsatisfied dependencies are remained:" >&2
+                       message_cat "${DBDIR}/unsatisfied.list"
+                       message_echo "*** Aborted by ${APPNAME}"
+                       message_echo "The ports tree seems broken. You might have caught an incomplete version."
+                       message_echo "You are encouraged to update the ports tree by portsnap(8)."
+                       message_echo "Then execute"
+                       message_echo " ${APPNAME} clean"
+                       message_echo "before restart."
+                       temp_terminate_process () { :; }
+                       exit 1
+               fi
+               message_echo
+       }
+       program_exec_and_record_completion ORDER_ALL_DEPENDENCIES
+}
+
+# ============= Selection of removing leaf ports =============
+command_do_selection_of_removing_leaf_ports ()
+{
+       local PROGRAM_DEPENDS
+       PROGRAM_DEPENDS='INSPECT_REQUIREMENTS_OF_LEAF_PORTS'
+       _program_exec_and_record_completion__operation ()
+       {
+               message_section_title "Selection of removing leaf ports"
+               deinstall_select_leaf_ports_to_delete
+               message_echo
+       }
+       program_exec_and_record_completion SELECT_LEAF_PORTS
+}
+
+# ============= Selection of removing obsolete ports =============
+command_do_selection_of_removing_obsolete_ports ()
+{
+       local PROGRAM_DEPENDS
+       PROGRAM_DEPENDS='INSPECT_ALL_DEPENDENCIES PARSE_CONF'
+       _program_exec_and_record_completion__operation ()
+       {
+               message_section_title "Selection of removing obsolete ports"
+               deinstall_select_obsolete_ports_to_delete
+               message_echo
+       }
+       program_exec_and_record_completion SELECT_OBSOLETE_PORTS
+}
+
+# ============= Collection of leaf ports to delete =============
+command_do_collection_of_leaf_ports_to_delete ()
+{
+       local PROGRAM_DEPENDS
+       if [ ! -e "${DBDIR}/inspected_ports_only_partially" ]
+       then
+               PROGRAM_DEPENDS='SELECT_LEAF_PORTS'
+               _program_exec_and_record_completion__operation ()
+               {
+                       local src src_unselected reqptn_file src_with_initial_origins
+                       message_section_title "Collecting leaf ports to delete"
+                       src=${DBDIR}/leaf_ports
+                       src_unselected=${DBDIR}/leaf_ports_to_delete.unselected
+                       src_with_initial_origins=${DBDIR}/leaf_ports.with_ini
+                       reqptn_file=${DBDIR}/leaf_ports.requirements_of_unselected
+                       cat "$src_unselected" 2> /dev/null | while read origin
+                       do
+                               cat "${DBDIR}/requires/$origin/requirements.all.full" "${DBDIR}/requires/$origin/ignored_requirements.all" || :
+                       done 2> /dev/null | sort -u > $reqptn_file
+                       database_query_add_initial_origins < $src > $src_with_initial_origins
+                       message_echo
+               }
+               program_exec_and_record_completion COLLECT_LEAF_PORTS_TO_DELETE
+       fi
+}
+
+# ============= Collection of obsolete ports to delete =============
+command_do_collection_of_obsolete_ports_to_delete ()
+{
+       local PROGRAM_DEPENDS
+       PROGRAM_DEPENDS='SELECT_OBSOLETE_PORTS'
+       _program_exec_and_record_completion__operation ()
+       {
+               local src src_selected src_unselected dst_selected reqptn_file
+               message_section_title "Collecting obsolete ports to delete"
+               src=${DBDIR}/obsolete_ports.can_be_deleted
+               src_selected=${DBDIR}/obsolete_ports_to_delete.selected
+               src_unselected=${DBDIR}/obsolete_ports_to_delete.unselected
+               dst_selected=${DBDIR}/obsolete_ports_to_delete
+               reqptn_file=${DBDIR}/obsolete_ports.requirements_of_unselected
+               cat "$src_unselected" 2> /dev/null | while read origin
+               do
+                       cat "${DBDIR}/initial/$origin/requirements.run.full" || :
+                       cat "${DBDIR}/obsolete/$origin/requirements.run.full" || :
+               done | sort -u > $reqptn_file
+               grep -v -Fx -f "$reqptn_file" "$src_selected" > $dst_selected 2> /dev/null || :
+               message_echo
+       }
+       program_exec_and_record_completion COLLECT_OBSOLETE_PORTS_TO_DELETE
+}
+
+# ============= Set up the list of ports to reinstall =============
+command_do_set_up_the_list_of_ports_to_reinstall ()
+{
+       local PROGRAM_DEPENDS
+       PROGRAM_DEPENDS='ORDER_ALL_DEPENDENCIES'
+       _program_exec_and_record_completion__operation ()
+       {
+               message_section_title "Setting up the list of ports to reinstall"
+               cp -p "${DBDIR}/reinst_order.list" "${DBDIR}/stage.loop_list/reinst_todo"
+               message_echo
+       }
+       program_exec_and_record_completion SETUP_REINST_TODO
+}
+
+# ============= Composition of a list for deinstallation of obsolete and leaf packages =============
+command_do_composition_of_a_list_for_deinstallation_of_obsolete_and_leaf_packages ()
+{
+       local PROGRAM_DEPENDS
+       PROGRAM_DEPENDS='COLLECT_LEAF_PORTS_TO_DELETE COLLECT_OBSOLETE_PORTS_TO_DELETE'
+       _program_exec_and_record_completion__operation ()
+       {
+               local reqptn_leaf reqptn_obs leaf_selected leaf_selected_src obs_selected obs_selected_src grepptn preserved
+               message_section_title "Composing a list for deinstallation of obsolete and leaf packages"
+               reqptn_leaf=${DBDIR}/leaf_ports.requirements_of_unselected
+               reqptn_obs=${DBDIR}/obsolete_ports.requirements_of_unselected
+               leaf_selected_src=${DBDIR}/leaf_ports_to_delete.selected
+               leaf_selected=${DBDIR}/leaf_ports_to_delete
+               obs_selected_src=${DBDIR}/obsolete_ports_to_delete.selected
+               obs_selected=${DBDIR}/obsolete_ports_to_delete
+               grepptn=${DBDIR}/ports_to_delete.grep_pattern
+               grepptn_col1=${DBDIR}/ports_to_delete.grep_pattern_col1
+               preserved=${TMPDIR}/LIST_DEINST_PKGS::preserved
+               if [ ! -e "${DBDIR}/inspected_ports_only_partially" ]
+               then
+                       cat "$reqptn_leaf" "$reqptn_obs" 2> /dev/null | sort -u > $grepptn
+                       grep -v -Fx -f "$grepptn" "$leaf_selected_src" 2> /dev/null \
+                               | database_query_add_initial_origins > $leaf_selected || :
+                       cat "$obs_selected" "$leaf_selected" 2> /dev/null || :
+               else
+                       rm -f "$leaf_selected"
+                       cat "$obs_selected" 2> /dev/null
+               fi | sort -u > ${DBDIR}/stage.loop_list/ports_to_delete
+               str_escape_regexp_filter < ${DBDIR}/stage.loop_list/ports_to_delete \
+                       | sed 's/^/^/;s/$/[[:space:]]/' > $grepptn_col1
+               cat "${DBDIR}/leaf_ports.with_ini" "${DBDIR}/obsolete_ports" 2> /dev/null \
+                       | grep -Fx -v -f "${DBDIR}/stage.loop_list/ports_to_delete" > ${DBDIR}/stage.loop_list/ports_to_restore 2> /dev/null || :
+               if [ $opt_batch_mode = no ]
+               then
+                       if [ ! -e "${DBDIR}/inspected_ports_only_partially" ] && \
+                               grep -v -Fx -f "${DBDIR}/stage.loop_list/ports_to_delete" "$leaf_selected_src" > $preserved 2> /dev/null
+                       then
+                               message_echo "INFO: Following leaf ports are preserved because required by other preserved leaf/obsolete ports."
+                               message_echo "----------------"
+                               while read origin
+                               do
+                                       pkgtag=`cat "${DBDIR}/moved_from/$origin/pkgtag" 2> /dev/null` || :
+                                       if [ -n "$pkgtag" ]
+                                       then
+                                               echo "$origin" "($pkgtag)"
+                                       else
+                                               echo "$origin"
+                                       fi
+                               done < $preserved
+                               message_echo "----------------"
+                       fi
+                       if grep -v -Fx -f "${DBDIR}/stage.loop_list/ports_to_delete" "$obs_selected_src" > $preserved 2> /dev/null
+                       then
+                               message_echo "INFO: Following obsolete ports are preserved because required by other obsolete ports."
+                               message_echo "----------------"
+                               while read origin
+                               do
+                                       pkgtag=`cat "${DBDIR}/initial/$origin/installed_version" 2> /dev/null` || :
+                                       if [ -n "$pkgtag" ]
+                                       then
+                                               echo "$origin" "($pkgtag)"
+                                       else
+                                               echo "$origin"
+                                       fi
+                               done < $preserved
+                               message_echo "----------------"
+                       fi
+               fi
+               message_echo
+       }
+       program_exec_and_record_completion LIST_DEINST_PKGS
+}
+
+# ============= Collect entire distfiles list =============
+command_do_collect_entire_distfiles_list ()
+{
+       local PROGRAM_DEPENDS
+       if [ $opt_inspect_entire_distinfo = yes ]
+       then
+               PROGRAM_DEPENDS=''
+               _program_exec_and_record_completion__operation ()
+               {
+                       message_section_title "Collecting entire distfiles list"
+                       find "${PORTSDIR}" -depth 3 -name distinfo -exec cat {} \; \
+                               | grep '^SHA256 ' | sed -E 's/^SHA256 \(([^)]*)\).*/\1/' \
+                               | sort -u > ${DBDIR}/distfiles.entire.tmp
+                       mv "${DBDIR}/distfiles.entire.tmp" "${DBDIR}/distfiles.entire"
+                       message_echo
+               }
+               program_exec_and_record_completion COLLECT_ALL_DISTFILES_LIST
+       fi
+}
+
+# ============= Inspection of all required distfiles =============
+command_do_inspection_of_all_required_distfiles ()
+{
+       local PROGRAM_DEPENDS
+       PROGRAM_DEPENDS='INSPECT_ALL_DEPENDENCIES COLLECT_ALL_DISTFILES_LIST'
+       _program_exec_and_record_completion__operation ()
+       {
+               message_section_title "Summarizing distfiles list"
+               {
+                       cat "${DBDIR}/distfiles.entire" || :
+                       cat "${DBDIR}/distfiles.inspected" || :
+               } 2> /dev/null | sort -u | str_escape_regexp_filter \
+                       | sed 's|^|^\\.\\/|; s|$|$|' > ${DBDIR}/distfiles.grep.pattern || :
+               message_echo
+       }
+       program_exec_and_record_completion DISTFILES_LIST
+}
+
+# ============= Clean up of reinstallation status for preparation =============
+command_do_clean_up_of_reinstallation_status_for_preparation ()
+{
+       local PROGRAM_DEPENDS
+       PROGRAM_DEPENDS='REDO_INIT INSPECT_ALL_DEPENDENCIES'
+       _program_exec_and_record_completion__operation ()
+       {
+               message_section_title "Cleaning up of reinstallation status for preparation"
+               rm -rf "${DBDIR}/status.ports"
+               message_echo
+       }
+       program_exec_and_record_completion CLEANUP_REINST_STATUS
+}
+
+# ============= Completion of building the temporary database =============
+command_do_completion_of_building_the_temporary_database ()
+{
+       local PROGRAM_DEPENDS
+       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 MAKE_IGNORED_DEPENDENTS_LISTS_UNIQUE COLLECT_LEAF_PORTS_TO_DELETE'
+       _program_exec_and_record_completion__operation ()
+       {
+               message_section_title "The temporary database is completely built up"
+               message_echo
+       }
+       program_exec_and_record_completion PREPARATION
+}
+
+# ============= End of do/redo prepare  =============
+command_do_end_at_prepare_complete ()
+{
+       local tmp_msg
+       tmp_msg=${TMPDIR}/command_do_end_at_prepare_complete:msg
+       cat > "$tmp_msg" << eof
+Done (skipped reinstallation) at `message_timestamp`
+
+ You can restart this process from the aborted/terminated point by executing without options or arguments as:
+  ${APPNAME}
+eof
+       message_cat "$tmp_msg"
+       temp_terminate_process () { :; }
+}
+
+# ============= Reinstallation of remained ports =============
+command_do_reinstallation_of_remained_ports ()
+{
+       local PROGRAM_DEPENDS
+       PROGRAM_DEPENDS='PREPARATION'
+       _program_exec_restartable_loop_operation__routine ()
+       {
+               reinstall_exec "$@"
+       }
+       _program_exec_and_record_completion__operation ()
+       {
+               local _MSG_CURRENT_STAGE_general
+               _MSG_CURRENT_STAGE_general="reinstallation"
+               temp_set_msg_current_stage "${_MSG_CURRENT_STAGE_general}"
+               message_section_title "Reinstallation"
+               program_exec_restartable_loop_operation reinst_todo
+               reinstall_restore_conflicts
+               temp_set_msg_current_stage
+               message_echo
+       }
+       program_exec_and_record_completion REINSTALLATION
+}
+
+# ============= Restoration of obsolete and leaf packages which have been deinstalled but unselected from the deletion list again  =============
+command_do_restore_needed_obsolete_and_leaf_packages ()
+{
+       local PROGRAM_DEPENDS
+       PROGRAM_DEPENDS='REDO_INIT LIST_DEINST_PKGS'
+       _program_exec_restartable_loop_operation__routine ()
+       {
+               deinstall_restore "$@"
+       }
+       _program_exec_and_record_completion__operation ()
+       {
+               local _MSG_CURRENT_STAGE_general
+               _MSG_CURRENT_STAGE_general="restoration of unselected obsolete/leaf packages"
+               temp_set_msg_current_stage "${_MSG_CURRENT_STAGE_general}"
+               message_section_title "Restoration of unselected obsolete/leaf packages"
+               program_exec_restartable_loop_operation ports_to_restore
+               temp_set_msg_current_stage
+               message_echo
+       }
+       program_exec_and_record_completion RESTORE_ONCE_DEINST_PKGS
+}
+
+# ============= Deinstallation of unused obsolete and leaf packages =============
+command_do_deinstallation_of_unused_obsolete_and_leaf_packages ()
+{
+       local PROGRAM_DEPENDS
+       PROGRAM_DEPENDS='REDO_INIT LIST_DEINST_PKGS'
+       _program_exec_restartable_loop_operation__routine ()
+       {
+               deinstall_exec "$@"
+       }
+       _program_exec_and_record_completion__operation ()
+       {
+               local _MSG_CURRENT_STAGE_general
+               _MSG_CURRENT_STAGE_general="deinstallation of obsolete/leaf packages"
+               temp_set_msg_current_stage "${_MSG_CURRENT_STAGE_general}"
+               message_section_title "Deinstallation of unused obsolete/leaf packages"
+               program_exec_restartable_loop_operation ports_to_delete
+               temp_set_msg_current_stage
+               message_echo
+       }
+       program_exec_and_record_completion DEINST_UNUSED_PKGS
+}
+
+# ============= Clean up obsolete or unused distfiles =============
+command_do_clean_up_obsolete_or_unused_distfiles ()
+{
+       local PROGRAM_DEPENDS
+       if [ $opt_only_target_scope = no -a $opt_keep_distfiles = no ]
+       then
+               PROGRAM_DEPENDS='REINSTALLATION DISTFILES_LIST'
+               _program_exec_and_record_completion__operation ()
+               {
+                       local tmp_distfiles_exists
+                       message_section_title "Cleaning up obsolete or unused distfiles"
+                       tmp_distfiles_exists=${TMPDIR}/CLEANUP_OBSLETE_DISTFILES::distfiles_exists
+                       [ $opt_dry_run = yes ] && message_echo "INFO: The operations are not actually carried out."
+                       ( set -e; cd "${DISTDIR}" && find . -type f ) \
+                               | sed 's|^\./||' | sort -u > $tmp_distfiles_exists
+                       fileedit_manipulate_old_lines "$tmp_distfiles_exists" "${DBDIR}/distfiles.entire" \
+                               | while read distfile
+                       do
+                               if [ $opt_batch_mode = no ]
+                               then
+                                       echo "  $distfile"
+                               fi
+                               [ $opt_dry_run = yes ] && continue
+                               rm -f "${DISTDIR}/$distfile"
+                       done
+                       message_echo
+               }
+               program_exec_and_record_completion CLEANUP_OBSLETE_DISTFILES
+       fi
+}
+
+# ============= Rebuild of package database =============
+command_do_rebuild_of_package_database ()
+{
+       local PROGRAM_DEPENDS
+       PROGRAM_DEPENDS='REINSTALLATION RESTORE_ONCE_DEINST_PKGS DEINST_UNUSED_PKGS'
+       _program_exec_and_record_completion__operation ()
+       {
+               which -s pkgdb || return 0
+               message_section_title "Rebuilding package database for portupgrade"
+               if grep -q @ "${DBDIR}/stage.loop_list/reinst_todo"
+               then
+                       message_echo "INFO: Skipped because of lacking flavor support."
+               else
+                       pkgdb -fu
+               fi
+               message_echo
+       }
+       program_exec_and_record_completion REBUILD_PKGDB
+}
+
+# =============Operation of redo command irrespective of option settings =============
+command_do_redo__command_all_exec_irrespective_of_saved_options ()
+{
+       [ $opt_reload_conf = yes ] || return 0
+       program_deregister_stage_complete SAVE_PREV_CONF
+       program_deregister_stage_complete ALL_COMPLETE
+       rm -f "${DBDIR}"/complete
+}
+
+# ============= Preparation of the temporary database =============
+command_do_prepare ()
+{
+       # Meta process for redo
+       command_do_meta_process_for_redo
+       
+       # Determine specified targets
+       command_do_determin_specified_targets
+       
+       # Show specified targets
+       command_do_show_specified_targets
+       
+       # Determine all target ports
+       command_do_determine_all_target_ports
+       
+       # Loop considering cases that port options are changed after inspection
+       while true
+       do
+               # Inspection of all dependencies
+               command_do_inspection_of_all_dependencies
+               
+               # Convert dependency-lists to actual ones
+               command_do_convert_dependency_lists_to_actual_ones
+               
+               # Completion of recursive requirement lists
+               command_do_completion_of_recursive_requirement_lists
+               
+               # Trim dependency lists by removing uninspected ports
+               command_do_trim_dependency_lists_by_removing_uninspected_ports
+               
+               # Inspection of dependents
+               command_do_inspection_of_dependents
+               
+               # End the loop when no change is made on port options after the inspection
+               command_do_reset_changed_portdb && break
+       done
+       
+       # Remove duplicated lines in dependents lists
+       command_do_remove_duplicated_lines_in_dependents_lists
+       
+       # Remove duplicated lines in ignored dependents lists
+       command_do_remove_duplicated_lines_in_ignored_dependents_lists
+       
+       # Preparation of target attribute information
+       command_do_preparation_of_target_attribute_information
+       
+       # Post-process after the preparation of target attribute information
+       command_do_post_process_after_the_preparation_of_target_attribute_information
+       
+       # Build of data on complement to new dependents for target attribute information
+       command_do_build_of_data_on_complement_to_new_dependents_for_target_attribute_information
+       
+       # Parse target attribute information
+       command_do_parse_target_attribute_information
+       
+       # Inspection of necessity
+       command_do_inspection_of_necessity
+       
+       # Inspection of necessary upgrades
+       command_do_inspection_of_necessary_upgrades
+       
+       # Preparation for inspection of new leaf ports
+       command_do_preparation_for_inspection_of_new_leaf_ports
+       
+       # Inspection of new primary leaf ports
+       command_do_inspection_of_new_primary_leaf_ports
+       
+       # Inspection of requirements of new leaf ports
+       command_do_inspection_of_requirements_of_new_leaf_ports
+       
+       # Order the ports considering dependencies
+       command_do_order_the_ports_considering_dependencies
+       
+       # Selection of removing leaf ports
+       command_do_selection_of_removing_leaf_ports
+       
+       # Selection of removing obsolete ports
+       command_do_selection_of_removing_obsolete_ports
+       
+       # Collection of leaf ports to delete
+       command_do_collection_of_leaf_ports_to_delete
+       
+       # Collection of obsolete ports to delete
+       command_do_collection_of_obsolete_ports_to_delete
+       
+       # Set up the list of ports to reinstall
+       command_do_set_up_the_list_of_ports_to_reinstall
+       
+       # Composition of a list for deinstallation of obsolete and leaf packages
+       command_do_composition_of_a_list_for_deinstallation_of_obsolete_and_leaf_packages
+       
+       # Collect entire distfiles list
+       command_do_collect_entire_distfiles_list
+       
+       # Inspection of all required distfiles
+       command_do_inspection_of_all_required_distfiles
+       
+       # Clean up of reinstallation status for preparation
+       command_do_clean_up_of_reinstallation_status_for_preparation
+       
+       # Completion of building the temporary database
+       command_do_completion_of_building_the_temporary_database
+}
+
+# ============= Reset the progress of reinstallation for retrial =============
+command_do_reset_for_reinst_retrial ()
+{
+       program_deregister_stage_complete REINSTALLATION
+       program_deregister_stage_complete RESTORE_ONCE_DEINST_PKGS
+       program_deregister_stage_complete DEINST_UNUSED_PKGS
+       rm -rf "${DBDIR}/status.ports" "${DBDIR}/new_success_in_current_run"
+}
+
+# ============= Main operation of do/redo =============
+command_do_main ()
+{
+       local ntrial
+       # Reset termination messages
+       temp_reset_termination_messages_common
+       
+       ntrial=0
+       while true
+       do
+               if [ $ntrial -gt 0 ]
+               then
+                       message_echo "########## RETRIAL ($ntrial) OF (RE)INSTALLATION ##########"
+                       message_echo
+               fi
+               
+               # Reinstallation of remained ports
+               command_do_reinstallation_of_remained_ports
+               
+               if [ $opt_fetch_only = yes ]
+               then
+                       message_echo "Completed the fetch only mode."
+                       exit
+               fi
+               
+               # Restoration of obsolete and leaf packages which have been deinstalled but unselected from the deletion list again 
+               command_do_restore_needed_obsolete_and_leaf_packages
+               
+               # Deinstallation of unused obsolete and leaf packages
+               command_do_deinstallation_of_unused_obsolete_and_leaf_packages
+               
+               # Clean up obsolete or unused distfiles
+               command_do_clean_up_obsolete_or_unused_distfiles
+               
+               # Rebuild of package database
+               command_do_rebuild_of_package_database
+               
+               # Retry if incomplete
+               command_do_is_everything_resolved && break
+               database_query_is_any_progress || break
+               command_do_reset_for_reinst_retrial
+               ntrial=$(($ntrial+1))
+       done
+       :
+}
+
+# ============= Check whether everything is resolved =============
+command_do_is_everything_resolved ()
+{
+       local subject
+       for subject in failure redo conflict
+       do
+               database_query_show_single_list_exec "$subject" \
+                       `options_get_dependency_type` `options_get_dependency_level` > dev/null 2> /dev/null && return 1
+       done
+       :
+}
+
+# ============= Notice of failures =============
+command_do_failure_notice ()
+{
+       local exists_unresolved_ports
+       exists_unresolved_ports=
+       message_summary_dependents_of_failed_reinstallation failure || exists_unresolved_ports=y
+       message_summary_dependents_of_failed_reinstallation redo || exists_unresolved_ports=y
+       message_summary_dependents_of_failed_reinstallation conflict || exists_unresolved_ports=y
+       [ "x$exists_unresolved_ports" = xy ] || return 0
+       message_summary_advice_on_manual_solution
+       return 1
+}
+
+# ============= Ending process =============
+command_do_ending_process ()
+{
+       local PROGRAM_DEPENDS
+       temp_terminate_process () { :; }
+       if command_do_failure_notice
+       then
+               if [ $opt_no_opening_message = yes ]
+               then
+                       message_echo "Done as ${APPNAME}"
+                       return
+               fi
+               message_section_title "COMPLETELY DONE"
+               if [ $opt_fetch_only = no -a $opt_dry_run = no ]
+                       then
+                       PROGRAM_DEPENDS='REBUILD_PKGDB CLEANUP_OBSLETE_DISTFILES '
+                       _program_exec_and_record_completion__operation ()
+                       {
+                       }
+                       program_exec_and_record_completion ALL_COMPLETE
+                       message_echo "- E N D -"
+               else
+                       message_echo "INFO: Redo for the real (re)installation."
+               fi
+       else
+               message_warn_no_achieved_progress
+               message_section_title "Done with some unresolved problems"
+               message_echo "- To be continued -"
+       fi
+}
diff --git a/lib/libcommand_flexconf.sh b/lib/libcommand_flexconf.sh
new file mode 100644 (file)
index 0000000..55e918d
--- /dev/null
@@ -0,0 +1,135 @@
+#!/bin/sh -e
+# ==============================================================================
+# portsreinstall library script
+# - Commands of flexible configuration -
+# Copyright (C) 2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# This software is distributed under the 2-Clause BSD License.
+# ==============================================================================
+
+# ============= Register/deregister ok ports in the command line form =============
+command_flexconf_update_ok ()
+{
+       local dbfile tmp_manually_done_diff
+       dbfile=${DBDIR}/manually_done.list
+       [ -e "$dbfile" ] || touch "$dbfile"
+       cp "$dbfile" "$dbfile.tmp"
+       shift || :
+       case $COMMAND_OPERATION in
+       add )
+               pkgsys_register_evaluated_globs add "$dbfile.tmp" "$@"
+               message_echo "`str_linearize_list_and \"$*\"` is/are registered to the list of manually resolved ports"
+               ;;
+       del )
+               pkgsys_register_evaluated_globs remove "$dbfile.tmp" "$@"
+               message_echo "`str_linearize_list_and \"$*\"` is/are deregistered from the list of manually resolved ports"
+               program_deregister_stage_complete REINSTALLATION
+               program_deregister_stage_complete ALL_COMPLETE
+               ;;
+       esac
+       tmp_manually_done_diff=${TMPDIR}/command_flexconf_update_ok:manually_done.list.diff
+       if fileedit_manipulate_old_new_lines "$dbfile" "$dbfile.tmp" \
+               "$tmp_manually_done_diff.old" "$tmp_manually_done_diff.new"
+       then
+               while read origin
+               do
+                       database_record_failure "$origin"
+               done < $tmp_manually_done_diff.old
+               while read origin
+               do
+                       database_record_success "$origin"
+               done < $tmp_manually_done_diff.new
+       fi
+       mv "$dbfile.tmp" "$dbfile"
+       message_echo "Now the following ports have been manually resolved:"
+       message_cat "$dbfile"
+}
+
+# ============= Register/deregister taboo ports in the command line form =============
+command_flexconf_update_taboo ()
+{
+       local COMMAND_OPERATION evalated_globs
+       COMMAND_OPERATION=$1
+       shift || :
+       evalated_globs=`str_linearize_list_and "$@"`
+       case $COMMAND_OPERATION in
+       add )
+               pkgsys_register_evaluated_globs add "${DBDIR}/taboo.list" "$@"
+               message_echo "$evalated_globs is/are registered to the list of taboo ports."
+               ;;
+       del )
+               pkgsys_register_evaluated_globs remove "${DBDIR}/taboo.list" "$@"
+               message_echo "$evalated_globs is/are deregistered from the list of taboo ports."
+               ;;
+       esac
+       fileedit_combine_lists "${DBDIR}/conf/TABOO:PORTS.parsed" "${DBDIR}/taboo.list" > ${DBDIR}/taboo.all.list
+       message_echo "Now the following ports are registered as taboo:"
+       message_cat "${DBDIR}/taboo.all.list"
+}
+
+# ============= Register/deregister freeze ports in the command line form =============
+command_flexconf_update_freeze ()
+{
+       local COMMAND_OPERATION evalated_globs
+       COMMAND_OPERATION=$1
+       shift || :
+       evalated_globs=`str_linearize_list_and "$@"`
+       case $COMMAND_OPERATION in
+       add )
+               pkgsys_register_evaluated_globs add "${DBDIR}/freeze.list" "$@"
+               message_echo "$evalated_globs is/are registered to the list of ports to freeze."
+               ;;
+       del )
+               pkgsys_register_evaluated_globs remove "${DBDIR}/freeze.list" "$@"
+               message_echo "$evalated_globs is/are deregistered from the list of ports to freeze."
+               ;;
+       esac
+       fileedit_combine_lists "${DBDIR}/conf/FREEZE:PORTS.parsed" "${DBDIR}/freeze.list" > ${DBDIR}/freeze.all.list
+       message_echo "Now the following ports are registered to freeze:"
+       message_cat "${DBDIR}/freeze.all.list"
+}
+
+# ============= Register/deregister needed ports in the command line form =============
+command_flexconf_update_need ()
+{
+       local COMMAND_OPERATION evalated_globs
+       COMMAND_OPERATION=$1
+       shift || :
+       evalated_globs=`str_linearize_list_and "$@"`
+       case $COMMAND_OPERATION in
+       add )
+               pkgsys_register_evaluated_globs add "${DBDIR}/need.list" "$@"
+               message_echo "$evalated_globs is/are registered to the list of necessary ports."
+               ;;
+       del )
+               pkgsys_register_evaluated_globs remove "${DBDIR}/need.list" "$@"
+               message_echo "$evalated_globs is/are deregistered from the list of necessary ports."
+               ;;
+       esac
+       {
+               sed -E -f "${DBDIR}/REPLACE.complete_sed_pattern" "${DBDIR}/need.list" || :
+               cat "${DBDIR}/need.list" || :
+       } 2> /dev/null | sort -u > ${DBDIR}/need.with_replaced.list
+       message_echo "Now the following ports are registered to be necessary:"
+       message_cat "${DBDIR}/need.list"
+}
+
+# ============= Register/deregister unneeded ports in the command line form =============
+command_flexconf_update_noneed ()
+{
+       local COMMAND_OPERATION evalated_globs
+       COMMAND_OPERATION=$1
+       shift || :
+       evalated_globs=`str_linearize_list_and "$@"`
+       case $COMMAND_OPERATION in
+       add )
+               pkgsys_register_evaluated_globs add "${DBDIR}/noneed.list" "$@"
+               message_echo "$evalated_globs is/are registered to the list of unnecessary ports."
+               ;;
+       del )
+               pkgsys_register_evaluated_globs remove "${DBDIR}/noneed.list" "$@"
+               message_echo "$evalated_globs is/are deregistered from the list of unnecessary ports."
+               ;;
+       esac
+       message_echo "Now the following ports are registered to be unnecessary:"
+       message_cat "${DBDIR}/noneed.list"
+}
diff --git a/lib/libcommand_forget.sh b/lib/libcommand_forget.sh
new file mode 100644 (file)
index 0000000..195d890
--- /dev/null
@@ -0,0 +1,126 @@
+#!/bin/sh -e
+# ==============================================================================
+# portsreinstall library script
+# - "forget" command operation -
+# Copyright (C) 2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# This software is distributed under the 2-Clause BSD License.
+# ==============================================================================
+
+# ============= Operation of forget command =============
+command_forget ()
+{
+       message_echo "The temporary database is trying to forget about the specified ports as much as possible."
+       message_echo "Concretely, the data on each of the specified ports and their requirements/dependents is removed unless initially installed or required by other preserved ports."
+       message_echo
+       
+       # Preparation for inspection of the specified ports
+       PROGRAM_DEPENDS=''
+       _program_exec_and_record_completion__operation ()
+       {
+               message_section_title "Preparation for inspection of the specified ports"
+               rm -rf "${DBDIR}/forget"
+               mkdir "${DBDIR}/forget"
+               for list in masters remove_scope
+               do
+                       rm -f "${DBDIR}/stage.loop_list/forget_$list"*
+               done
+               message_echo
+       }
+       program_exec_and_record_completion FORGET::PREPARATION_INSPECT_MASTER
+       
+       # (Re)initialization of the specified ports to inspect
+       pkgsys_eval_ports_glob "$@" > ${DBDIR}/stage.loop_list/forget_masters
+       
+       # Inspection of the specified ports
+       PROGRAM_DEPENDS='FORGET::PREPARATION_INSPECT_MASTER'
+       _program_exec_restartable_loop_operation__routine ()
+       {
+               local origin origin_orig
+               origin=$1
+               if [ -e "${DBDIR}/REVERSE_REPLACE.complete_sed_pattern" ]
+               then
+                       origin_orig=`echo "$origin" \
+                               | sed -E -f "${DBDIR}/REVERSE_REPLACE.complete_sed_pattern"`
+               else
+                       origin_orig=$origin
+               fi
+               if [ ! -e "${DBDIR}/initial/$origin/installed_version" \
+                       -a ! -e "${DBDIR}/initial/$origin_orig/installed_version" \
+                       -a `cat "${DBDIR}/requires/$origin/dependents.all.full" 2> /dev/null | wc -l` -eq 0 ]
+               then
+                       message_echo "$origin"
+                       echo "$origin" >> ${DBDIR}/forget/remove.master
+                       cat "${DBDIR}/requires/$origin/requirements.all.full" \
+                               2> /dev/null >> ${DBDIR}/forget/remove.scope || :
+                       database_build_forget "$origin"
+               fi
+       }
+       _program_exec_and_record_completion__operation ()
+       {
+               message_section_title "Inspection of the specified ports"
+               message_echo "----------------"
+               program_exec_restartable_loop_operation forget_masters
+               message_echo "----------------"
+               cat "${DBDIR}/forget/remove.scope" 2> /dev/null \
+                       | sort -u > ${DBDIR}/forget/remove.scope.tmp
+               mv "${DBDIR}/forget/remove.scope.tmp" "${DBDIR}/forget/remove.scope"
+               {
+                       cat "${DBDIR}/forget/remove.master" || :
+                       cat "${DBDIR}/forget/remove.scope" || :
+               } 2> /dev/null | sort -u > ${DBDIR}/forget/remove.scope.filter
+               ln -f "${DBDIR}/forget/remove.scope" "${DBDIR}/stage.loop_list/forget_remove_scope"
+               message_echo
+       }
+       program_exec_and_record_completion FORGET::INSPECT_MASTER
+       
+       # Inspection of the requirements of the specified ports to remove
+       PROGRAM_DEPENDS='FORGET::INSPECT_MASTER'
+       _program_exec_restartable_loop_operation__routine ()
+       {
+               local origin origin_orig
+               origin=$1
+               if [ -e "${DBDIR}/REVERSE_REPLACE.complete_sed_pattern" ]
+               then
+                       origin_orig=`echo "$origin" \
+                               | sed -E -f "${DBDIR}/REVERSE_REPLACE.complete_sed_pattern"`
+               else
+                       origin_orig=$origin
+               fi
+               if [ ! -e "${DBDIR}/initial/$origin/installed_version" \
+                       -a ! -e "${DBDIR}/initial/$origin_orig/installed_version" ] \
+                       && ! grep -qv -Fx -f "${DBDIR}/forget/remove.scope.filter" \
+                               "${DBDIR}/requires/$origin/dependents.all.full" \
+                               2> /dev/null
+               then
+                       message_echo "$origin"
+                       database_build_forget "$origin"
+                       echo "$origin" >> ${DBDIR}/forget/remove
+               fi
+       }
+       _program_exec_and_record_completion__operation ()
+       {
+               message_section_title "Inspection of the requirements of the specified ports to remove"
+               message_echo "----------------"
+               program_exec_restartable_loop_operation forget_remove_scope
+               message_echo "----------------"
+               {
+                       cat "${DBDIR}/forget/remove.master" || :
+                       cat "${DBDIR}/forget/remove" || :
+               } 2> /dev/null | sort -u > ${DBDIR}/forget/remove.filter
+               cat "${DBDIR}/inspected_ports.update" 2> /dev/null | sort -u \
+                       | grep -v -Fx -f "${DBDIR}/forget/remove.filter" \
+                               > ${DBDIR}/inspected_ports.update.tmp 2> /dev/null || :
+               mv "${DBDIR}/inspected_ports.update.tmp" "${DBDIR}/inspected_ports.update"
+               message_echo
+       }
+       program_exec_and_record_completion FORGET::INSPECT_REQUIREMENTS_OF_REMOVED_PORTS
+       
+       # Set up so that ports are inspected again in the building process of the temporary database
+       program_deregister_stage_complete INSPECT_ALL_DEPENDENCIES
+       
+       # Clean up the database for this command because it is no more effective
+       program_deregister_stage_complete FORGET::PREPARATION_INSPECT_MASTER
+       
+       # Invalidate the completion
+       program_deregister_stage_complete ALL_COMPLETE
+}
diff --git a/lib/libcommand_pkgs.sh b/lib/libcommand_pkgs.sh
new file mode 100644 (file)
index 0000000..0a581ed
--- /dev/null
@@ -0,0 +1,434 @@
+#!/bin/sh -e
+# ==============================================================================
+# portsreinstall library script
+# - Commands of ports/packages operations -
+# Copyright (C) 2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# This software is distributed under the 2-Clause BSD License.
+# ==============================================================================
+
+# ============= Operation of reconf/rmconf command =============
+command_pkgs_port_option_conf ()
+{
+       local make_target origin
+       case $COMMAND_MODE in
+       reconf )
+               message_echo "Reconfigure the specified port options."
+               make_target=config
+               ;;
+       rmconf )
+               message_echo "The specified port options are reset to the default."
+               make_target=rmconfig
+               ;;
+       esac
+       message_echo "Affected parts of the temporary database are reset automatically."
+       for origin in `pkgsys_eval_ports_glob "$@"`
+       do
+               message_echo "Re-configure $origin:"
+               database_build_make "$origin" $make_target
+               database_build_patch_reconf "$origin"
+       done
+       program_deregister_stage_complete INSPECT_ALL_DEPENDENCIES
+       program_deregister_stage_complete ALL_COMPLETE
+}
+
+# ============= Operation of escape command =============
+command_pkgs_escape ()
+{
+       local origin pkg backup_pkg
+       message_echo "Backing up and deleting the following packages for a temporary escape:"
+       message_echo
+       for origin in `pkgsys_eval_ports_glob "$@"`
+       do
+               pkgsys_register_evaluated_globs add "${DBDIR}/taboo.list" "$origin"
+               message_echo "  Registered $origin as taboo."
+               pkg=`pkgsys_get_installed_pkg_from_origin "$origin"`
+               [ -n "$pkg" ] || continue
+               if backup_pkg=`pkgsys_get_backup_pkg "$origin"`
+               then
+                       message_echo "INFO: A backup package for $pkg ($origin) already exists as $backup_pkg."
+               elif backup_pkg=`pkgsys_create_backup_pkg "$pkg" "${DBDIR}/backup_packages"`
+               then
+                       message_echo "  Backed up $pkg ($origin) into $backup_pkg"
+               else
+                       message_echo "ERROR: Failed to back up $pkg ($origin)." >&2
+                       message_echo >&2
+                       continue
+               fi
+               pkg_delete_f "$pkg" || \
+               {
+                       message_echo "ERROR: Failed to deinstall $pkg ($origin)." >&2
+                       message_echo >&2
+               }
+               message_echo "  Deinstalled $pkg ($origin)."
+               message_echo
+       done
+       fileedit_combine_lists "${DBDIR}/conf/TABOO:PORTS.parsed" "${DBDIR}/taboo.list" > ${DBDIR}/taboo.all.list
+}
+
+# ============= Operation of restore command =============
+command_pkgs_restore ()
+{
+       local tmp_done_orig origin pkg origin_orig pkg_orig origin_replace pkg_replace backup_pkg
+       message_echo "Restoring the following temporary escaped packages:"
+       message_echo
+       tmp_done_orig=${TMPDIR}/command_pkgs_restore::restore::done_orig
+       cp /dev/null "$tmp_done_orig"
+       for origin in `pkgsys_eval_ports_glob "$@"`
+       do
+               pkgsys_register_evaluated_globs remove "${DBDIR}/taboo.list" "$origin"
+               message_echo "  Deregistered $origin from taboo."
+               grep -Fx -q "$origin" "$tmp_done_orig" 2> /dev/null || :
+               if pkgsys_exists_from_orig "$origin"
+               then
+                       pkg=`pkgsys_get_installed_pkg_from_origin "$origin"`
+                       message_echo "WARNING: $pkg ($origin) is already installed." >&2
+                       message_echo >&2
+                       continue
+               fi
+               origin_orig=`echo "$origin" \
+                       | sed -E -f "${DBDIR}/REVERSE_REPLACE.complete_sed_pattern"`
+               if [ "x$origin_orig" = "x$origin" ] && pkgsys_exists_from_orig "$origin_orig"
+               then
+                       pkg_orig=`pkgsys_get_installed_pkg_from_origin "$origin_orig"`
+                       message_echo "WARNING: An original version of $origin ($pkg_orig, $origin_orig) is already installed." >&2
+                       message_echo >&2
+                       continue
+               fi
+               origin_replace=`echo "$origin" \
+                       | sed -E -f "${DBDIR}/REPLACE.complete_sed_pattern"`
+               if [ "x$origin_replace" != "x$origin" ]
+               then
+                       if pkgsys_exists_from_orig "$origin_replace"
+                       then
+                               pkg_replace=`pkgsys_get_installed_pkg_from_origin "$origin_replace"`
+                               message_echo "WARNING: A replacement of $origin ($pkg_replace, $origin_replace) is already installed." >&2
+                               message_echo >&2
+                               continue
+                       fi
+                       if backup_pkg=`pkgsys_get_backup_pkg "$origin_replace" 2> /dev/null`
+                       then
+                               message_echo "INFO: $origin is replaced with $origin_replace ($pkg_replace)."
+                               echo "$origin_replace" >> $tmp_done_orig
+                               origin=$origin_replace
+                       fi
+               else
+                       backup_pkg=
+               fi
+               if [ -z "$backup_pkg" ] && ! backup_pkg=`pkgsys_get_backup_pkg "$origin" 2> /dev/null`
+               then
+                       message_echo "ERROR: Backup for $origin is not found." >&2
+                       message_echo >&2
+                       continue
+               fi
+               pkg=`pkgsys_pkgarc_to_pkgname "$backup_pkg"`
+               if reinstall_chk_forbidden_conflicts "$pkg"
+               then
+                       message_echo "WARNING: $pkg ($origin) is skipped because it conflicts with installed packages." >&2
+                       message_echo >&2
+                       continue
+               fi
+               if ! pkg_add_fF "$backup_pkg"
+               then
+                       message_echo "ERROR: Failed to restore $pkg ($origin)." >&2
+                       message_echo >&2
+               fi
+               message_echo "  Restored $pkg ($origin)."
+               message_echo
+       done
+       fileedit_combine_lists "${DBDIR}/conf/TABOO:PORTS.parsed" "${DBDIR}/taboo.list" > ${DBDIR}/taboo.all.list
+}
+
+# ============= Operation of pkgsanity command =============
+command_pkgs_pkgsanity ()
+{
+       local tmp_list nlines iline pkg origin port_path is_reinstall_encouraged
+       tmp_list=${TMPDIR}/command_pkgs_pkgsanity:list
+       if [ $# -eq 0 ]
+       then
+               message_echo "Sanity check of the installed files for each package:"
+               message_echo
+               pkg_info_Ea > $tmp_list.pkgs
+               pkg_info_all_flavored_origins > $tmp_list.orgs
+       else
+               message_echo "Examining the installed files for each specified package:"
+               message_echo
+               pkgsys_eval_ports_glob "$@" > $tmp_list.orgs
+               while read origin
+               do
+                       pkgsys_get_installed_pkg_from_origin "$origin"
+               done < $tmp_list.orgs | grep -v '^[[:space:]]*$' > $tmp_list.pkgs || {
+                       message_echo "WARNING: No such globs match any installed package." >&2
+                       temp_terminate_process () { :; }
+                       exit 1
+               }
+       fi
+       message_echo "<< Phase 1: Check and fix duplicated packages registrations for the same port origin >>"
+       message_echo
+       while read origin
+       do
+               [ `pkgsys_get_installed_pkg_from_origin "$origin" | wc -l` -gt 1 ] || continue
+               pkgsys_get_installed_pkg_from_origin "$origin" | while read pkg
+               do
+                       echo "$((0+`pkg_check_sanity \"$pkg\" | wc -l`))" "$pkg"
+               done | sort -g > $tmp_list.pkgs_for_an_org
+               pkg_valid=`head -n 1 "$tmp_list.pkgs_for_an_org" | cut -d ' ' -f 2`
+               message_echo "Port [$origin] has multiply registered packages."
+               message_echo "The valid one will be [$pkg_valid]."
+               message_echo "Invalid one(s) will be as follows and to be deleted:"
+               sed 1d "$tmp_list.pkgs_for_an_org" | cut -d ' ' -f 2 > $tmp_list.pkgs_for_an_org_msg
+               message_cat "$tmp_list.pkgs_for_an_org_msg"
+               errout=/dev/stderr
+               [ $opt_batch_mode = yes ] && errout=/dev/null
+               if backup_pkg=`pkgsys_create_backup_pkg "$pkg_valid" "${DBDIR}/backup_packages"`
+               message_echo
+               then
+                       pkg_delete_f `cat "$tmp_list.pkgs_for_an_org"` 2> $errout || {
+                               message_echo "WARNING: Deletion of the broken packages may not be fully successful, but continuing anyway." >&2
+                               message_echo >&2
+                       }
+                       pkg_add_fF "$backup_pkg" || {
+                               message_echo "WARNING: Reinstallation of the most valid package failed, but continuing anyway." >&2
+                               message_echo >&2
+                       }
+               else
+                       message_echo "WARNING: Backup of the most valid package failed, but continuing anyway." >&2
+                       pkg_delete_f `cat "$tmp_list.pkgs_for_an_org"` 2> $errout || {
+                               message_echo "WARNING: Deletion of the broken packages may not be fully successful, but continuing anyway." >&2
+                               message_echo >&2
+                       }
+               fi
+       done < $tmp_list.orgs
+       
+       message_echo "<< Phase 2: Check and mark broken packages for reinstallation >>"
+       message_echo
+       nlines=`wc -l < $tmp_list.pkgs`
+       iline=1
+       while [ $iline -le $nlines ]
+       do
+               pkg=`sed -n ${iline}p "$tmp_list.pkgs"`
+               iline=$((${iline}+1))
+               origin=`pkg_info_flavored_origin "$pkg"`
+               [ -n "$origin" ] || continue
+               grep -q -Fx "$origin" "${DBDIR}/damaged_package" 2>/dev/null && continue
+               pkgsys_sanitychk_pkgcontents "$pkg" is_reinstall_encouraged && continue
+               port_path=`pkgsys_get_portpath_from_origin "$origin"`
+               if [ ! -d "$port_path" ]
+               then
+                       message_echo "WARNING: $pkg ($origin) is obsolete." >&2
+                       message_echo >&2
+                       continue
+               fi
+               if [ $is_reinstall_encouraged = no ]
+               then
+                       if [ $opt_batch_mode = no ]
+                       then
+                               message_echo "Do you want to reinstall it? (y/[n])"
+                               message_query_yn_default_no || continue
+                       fi
+               else
+                       if [ $opt_batch_mode = no ]
+                       then
+                               message_echo "Do you want to reinstall it? ([y]/n)"
+                               message_query_yn_default_yes || continue
+                       fi
+                       database_record_reconf_recover_sanity "$origin"
+               fi
+       done
+}
+
+# ============= Operation of packupgrade command =============
+command_pkgs_packupgrade ()
+{
+       case ${COMMAND_OPERATION} in
+       clean )
+               command_pkgs_packupgrade_clean
+               ;;
+       create )
+               command_pkgs_packupgrade_create
+               ;;
+       crop )
+               command_pkgs_packupgrade_crop
+               ;;
+       esac
+}
+
+# ============= Operation of packupgrade clean command =============
+command_pkgs_packupgrade_clean ()
+{
+       program_deregister_stage_complete COMMAND_PACKUPGRADE_PREPARE
+       rm -rf "${DBDIR}/command_packupgrade"
+}
+
+# ============= Stage of preparation in operation of packupgrade create command =============
+command_pkgs_packupgrade_create__prepare ()
+{
+       local PROGRAM_DEPENDS
+       PROGRAM_DEPENDS=
+       _program_exec_and_record_completion__operation ()
+       {
+               local dstdir
+               message_section_title "Preparation"
+               mkdir -p "${PACKAGES}/${PKGREPOSITORYSUBDIR}"
+               cp "${DBDIR}/reinst_order.list" "${DBDIR}/stage.loop_list/command_packupgrade_pack"
+               dstdir=${DBDIR}/command_packupgrade
+               rm -rf "$dstdir" "$dstdir.tar.gz"
+               mkdir -p "$dstdir"
+               install -d "$dstdir/etc"
+               touch "$dstdir/etc/created_packages.lst"
+               pkg_get_pkgs_timestamps > $dstdir/etc/final_pkgs_snapshot.csv
+               message_echo
+       }
+       program_exec_and_record_completion COMMAND_PACKUPGRADE_PREPARE
+}
+
+# ============= Stage of creating the manifest of reinstallation in operation of packupgrade create command =============
+command_pkgs_packupgrade_create__manifest_reinst ()
+{
+       local PROGRAM_DEPENDS
+       PROGRAM_DEPENDS=COMMAND_PACKUPGRADE_PREPARE
+       _program_exec_restartable_loop_operation__routine ()
+       {
+               local origin dstdir tmp_manifest dbdir_new pkgname pkgarc timestamp_inst timestamp_arc origin_old
+               origin=$1
+               dstdir=${DBDIR}/command_packupgrade
+               tmp_manifest=${TMPDIR}/packupgrade::manifest
+               rm -rf "$tmp_manifest"
+               dbdir_new=${DBDIR}/requires/$origin
+               pkgname=`pkgsys_get_installed_pkg_from_origin "$origin"`
+               [ -n "$pkgname" ] || return 0
+               if ! grep -Fxq "$pkgname" "$dstdir/etc/created_packages.lst" 2> /dev/null
+               then
+                       if pkg_info_e "$pkgname"
+                       then
+                               pkgarc=`pkgsys_pkgname_to_pkgarc "${PACKAGESDIR}" "$pkgname"`
+                               timestamp_inst=`pkg_get_pkg_timestamp "$pkgname" 2> /dev/null` || :
+                               timestamp_arc=`ls -lD %s "$pkgarc" 2> /dev/null | sed -E 's/[[:space:]]+/ /g' | cut -w -f 6 | grep -v '^$'` || :
+                               if [ -z "$timestamp_inst" -o -z "$timestamp_arc" -o "$timestamp_arc" -lt "$timestamp_inst" ]
+                               then
+                                       if ! ( cd ${PACKAGESDIR}; pkg_create_b "$pkgname" | message_cat )
+                                       then
+                                               message_echo "ERROR: Failed to create package [$pkgname for $origin]." >&2
+                                               exit 1
+                                       fi
+                               fi
+                       elif grep -Fxq "$origin" ${DBDIR}/success.run.full.list
+                       then
+                               message_echo "ERROR: Necessary package is missing [$origin]." >&2
+                               exit 1
+                       fi
+                       fileedit_add_a_line_if_new "$pkgname" "$dstdir/etc/created_packages.lst"
+               fi
+               if pkgsys_is_necessary_pkgtool "$origin"
+               then
+                       pkg_patterns=`pkgsys_get_conflicting_pkgs_patterns install "$origin" | tr '\n' '|'`
+                       printf '%s\t%s\t%s\n' addtool "$pkgname" "$origin|$pkg_patterns" >> $tmp_manifest
+               else
+                       if [ -e "${DBDIR}/moved_from/$origin/initial_orig" ]
+                       then
+                               while read origin_old
+                               do
+                                       printf '%s\t%s\t%s\n' delete "$pkgname" "$origin_old" 
+                               done < ${DBDIR}/moved_from/$origin/initial_orig >> $tmp_manifest
+                       fi
+                       printf '%s\t%s\t%s\n' delete "$pkgname" "$origin" >> $tmp_manifest
+                       pkgsys_get_conflicting_pkgs_patterns install "$origin" | while read pkg_pattern
+                       do
+                               printf '%s\t%s\t%s\n' delete_pattern "$pkgname" "$pkg_pattern" >> $tmp_manifest
+                       done
+                       printf '%s\t%s\t%s\n' add "$pkgname" null >> $tmp_manifest
+               fi
+               cat "$tmp_manifest" >> $dstdir/etc/manifest.lst
+       }
+       _program_exec_and_record_completion__operation ()
+       {
+               local PACKAGESDIR
+               message_section_title "Creating manifest of (re)installation and package archives..."
+               PACKAGESDIR=`realpath "${PACKAGES}/${PKGREPOSITORYSUBDIR}"`
+               program_exec_restartable_loop_operation command_packupgrade_pack
+               cp "${DBDIR}/stage.loop_list/ports_to_delete" "${DBDIR}/stage.loop_list/command_packupgrade_delete"
+               message_echo
+       }
+       program_exec_and_record_completion COMMAND_PACKUPGRADE_MANIFEST_REINST
+}
+
+# ============= Stage of creating the manifest of deletion in operation of packupgrade create command =============
+command_pkgs_packupgrade_create__manifest_delete ()
+{
+       local PROGRAM_DEPENDS
+       PROGRAM_DEPENDS='COMMAND_PACKUPGRADE_MANIFEST_REINST'
+       _program_exec_restartable_loop_operation__routine ()
+       {
+               local origin
+               origin=$1
+               printf '%s\t%s\t%s\n' delete "$pkgname" "$origin" >> ${DBDIR}/command_packupgrade/etc/manifest.lst
+       }
+       _program_exec_and_record_completion__operation ()
+       {
+               message_section_title "Create manifest of deletion"
+               program_exec_restartable_loop_operation command_packupgrade_delete
+               message_echo
+       }
+       program_exec_and_record_completion COMMAND_PACKUPGRADE_MANIFEST_DELETE
+}
+
+# ============= Stage of packing in operation of packupgrade create command =============
+command_pkgs_packupgrade_create__pack ()
+{
+       local PROGRAM_DEPENDS
+       PROGRAM_DEPENDS='COMMAND_PACKUPGRADE_MANIFEST_DELETE'
+       _program_exec_and_record_completion__operation ()
+       {
+               local dstdir
+               message_section_title "Packing for the upgrade at the target systems"
+               dstdir=${DBDIR}/command_packupgrade
+               install -m 444 "${DBDIR}"/WITH_PKGNG "${DBDIR}"/conf/complete_setup.sh "${DBDIR}"/conf/setenv.sh "$dstdir/etc"
+               install "${SHAREDIR}/bin/${APPNAME}-upgrade" "$dstdir"
+               install -d "$dstdir/lib/upgrade" "$dstdir/man/man8"
+               ( cd "${LIBDIR}" && find . upgrade -depth 1 -type f ) | while read filepath
+               do
+                       install -m 444 "${LIBDIR}/$filepath" "$dstdir/lib/$filepath"
+               done
+               install -m 444 "${MYPREFIX}/man/man8/${PROGRAM}-upgrade.8.gz" "$dstdir/man/man8"
+               tar czf "$dstdir.tar.gz" -C "$dstdir" .
+               touch "$dstdir/complete"
+               message_echo
+       }
+       program_exec_and_record_completion COMMAND_PACKUPGRADE_PACK
+}
+
+# ============= Operation of packupgrade create command =============
+command_pkgs_packupgrade_create ()
+{
+       if ! program_chk_stage_complete ALL_COMPLETE
+       then
+               message_echo "ERROR: The reinstallation of ports must be completed before using this command." >&2
+               exit 1
+       fi
+       # Preparation
+       command_pkgs_packupgrade_create__prepare
+       # Create manifest of (re)installation and package archives
+       command_pkgs_packupgrade_create__manifest_reinst
+       # Create manifest of deletion
+       command_pkgs_packupgrade_create__manifest_delete
+       # Packing for the upgrade at the target systems
+       command_pkgs_packupgrade_create__pack
+}
+
+# ============= Operation of packupgrade crop command =============
+command_pkgs_packupgrade_crop ()
+{
+       local dstdir
+       if ! program_chk_stage_complete ALL_COMPLETE
+       then
+               message_echo "ERROR: The reinstallation of ports must be completed before using this command." >&2
+               exit 1
+       fi
+       dstdir=${DBDIR}/command_packupgrade
+       if [ ! -e "$dstdir/complete" ]
+       then
+               message_echo "ERROR: The execution of \"packupgrade create\" command must be completed before using this command." >&2
+               exit 1
+       fi
+       cp "$dstdir.tar.gz" "${COMMAND_PACKUPGRADE_SAVEPATH}"
+       message_echo "INFO: The cropped archive is saved as [${COMMAND_PACKUPGRADE_SAVEPATH}]."
+}
diff --git a/lib/libcommand_show.sh b/lib/libcommand_show.sh
new file mode 100644 (file)
index 0000000..43b1523
--- /dev/null
@@ -0,0 +1,79 @@
+#!/bin/sh -e
+# ==============================================================================
+# portsreinstall library script
+# - "show" command operation -
+# Copyright (C) 2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# This software is distributed under the 2-Clause BSD License.
+# ==============================================================================
+
+# ============= Execute command operations which should be done without upgrade of tools =============
+command_show ()
+{
+       local flag_filter_skip_unchanged flag_filter_only_target listdb pkgnamedb dbsuffix list origin_target
+       flag_filter_skip_unchanged=
+       flag_filter_only_target=
+       pkgnamedb='moved_from obsolete initial'
+       [ -n "$COMMAND_SHOW_DEPTAG" ] || COMMAND_SHOW_DEPTAG=`options_get_dependency_type`
+       [ -n "$COMMAND_SHOW_LEVEL" ] || COMMAND_SHOW_LEVEL=`options_get_dependency_level`
+       dbsuffix=$COMMAND_SHOW_DEPTAG.$COMMAND_SHOW_LEVEL
+       case $COMMAND_SHOW_SUBJECT in
+       todo | done | redo | resolved | failure | taboo | freeze | need | noneed | deleted | restored | conflict )
+               database_query_show_single_list_exec "$COMMAND_SHOW_SUBJECT" \
+                       "$COMMAND_SHOW_DEPTAG" "$COMMAND_SHOW_LEVEL" || :
+               ;;
+       initrequirements )
+               grandtitle="Dependencies based on the initially installed packages"
+               title="The following port(s) was/were required by %s:"
+               list=requirements.$dbsuffix
+               listdb='initial'
+               pkgnamedb='initial'
+               [ $COMMAND_SHOW_DEPTAG = none ] && \
+                       message_echo "WARNING: This command has no meaning with the current options setting." >&2
+               database_query_show_port_lists "$grandtitle" "$title" "$list" "$listdb" "$pkgnamedb" "$@"
+               ;;
+       requirements )
+               grandtitle="Dependencies based on the latest ports tree"
+               title="The following port(s) is/are required by %s:"
+               list=requirements.$dbsuffix
+               listdb='requires'
+               pkgnamedb='moved_from'
+               [ $COMMAND_SHOW_DEPTAG = none ] && \
+                       message_echo "WARNING: This command has no meaning with the current options setting." >&2
+               database_query_show_port_lists "$grandtitle" "$title" "$list" "$listdb" "$pkgnamedb" "$@"
+               ;;
+       initdependents )
+               grandtitle="Dependencies based on the initially installed packages"
+               title="The following port(s) depended on %s:"
+               list=dependents.$dbsuffix
+               listdb='initial'
+               pkgnamedb='initial'
+               [ $COMMAND_SHOW_DEPTAG = none ] && \
+                       message_echo "WARNING: This command has no meaning with the current options setting." >&2
+               database_query_show_port_lists "$grandtitle" "$title" "$list" "$listdb" "$pkgnamedb" "$@"
+               ;;
+       dependents )
+               grandtitle="Dependencies based on the latest ports tree"
+               title="The following port(s) depend(s) on %s:"
+               list=dependents.$dbsuffix
+               listdb='requires'
+               pkgnamedb='moved_from'
+               [ $COMMAND_SHOW_DEPTAG = none ] && \
+                       message_echo "WARNING: This command has no meaning with the current options setting." >&2
+               database_query_show_port_lists "$grandtitle" "$title" "$list" "$listdb" "$pkgnamedb" "$@"
+               ;;
+       conflict_files )
+               grandtitle="Possible additional conflict files"
+               title="The following packages' files conflict with %s:"
+               list=possible_additional_conflist.csv
+               listdb='requires'
+               pkgnamedb='moved_from'
+               database_query_show_two_column_lists "$grandtitle" "$title" "$list" "$listdb" "$pkgnamedb" "$@"
+               ;;
+       status )
+               grandtitle="Success/failure status in (re)installation"
+               lists='todo|done|redo|resolved|failure|taboo|freeze|need|noneed|deleted|restored|conflict'
+               database_query_show_list_inclusion_of_matching_port "$grandtitle" "$lists" "$pkgnamedb" \
+                       "$COMMAND_SHOW_DEPTAG" "$COMMAND_SHOW_LEVEL" "$@"
+               ;;
+       esac
+}
index 3a2f413..133efb2 100644 (file)
@@ -2,7 +2,7 @@
 # ==============================================================================
 # portsreinstall library script
 # - Parsing of configuration files -
-# Copyright (C) 2013-2017 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# Copyright (C) 2013-2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
 # This software is distributed under the 2-Clause BSD License.
 # ==============================================================================
 
@@ -76,7 +76,7 @@ conf_parse_vars_for_each_port_glob_with_bound_val ()
                pkgsys_eval_ports_glob "$glob_pattern" | while read origin
                do
                        path=${DBDIR}/conf/each_port/$origin
-                       [ -d "$path" ] || mkdir -p "$path"
+                       mkdir -p "$path"
                        echo "$val" > $path/${section}.conf
                done
        done
@@ -93,8 +93,8 @@ conf_parse_pkgtools_conf ()
                message_echo "WARNING: portupgrade is not found, pkgtools.conf is ignored" >&2
                return
        fi
-       portupgrade_pkg=`pkg_info_qO ports-mgmt/portupgrade`
-       [ -n "$portupgrade_pkg" ] || portupgrade_pkg=`pkg_info_qO ports-mgmt/portupgrade-devel`
+       portupgrade_pkg=`pkgsys_get_installed_pkg_from_origin ports-mgmt/portupgrade`
+       [ -n "$portupgrade_pkg" ] || portupgrade_pkg=`pkgsys_get_installed_pkg_from_origin ports-mgmt/portupgrade-devel`
        [ `expr "$portupgrade_pkg" : '^portupgrade-devel-'` -eq 0 ] \
                || message_echo "WARNING: Combination with portupgrade-devel-* has not tested." >&2
        sed -n '/^def init_global$/,/^end$/p' "$PORTUPGRADE" > $tmp_script_crop
@@ -188,15 +188,15 @@ eof
 conf_get_complete_var_defs ()
 {
        case `options_get_effective_opt_load_pkgtoolsconf` in
-       default)
+       default )
                conf_parse_pkgtools_conf
                cat "${DBDIR}/conf/pkgtools.parsed" "${CONFFILE}" 2> /dev/null || :
                ;;
-       override)
+       override )
                conf_parse_pkgtools_conf
                cat "${CONFFILE}" "${DBDIR}/conf/pkgtools.parsed" 2> /dev/null || :
                ;;
-       no)
+       no )
                cat "${CONFFILE}" 2> /dev/null || :
                ;;
        esac
@@ -207,7 +207,7 @@ conf_manipulate_available_var_defs ()
 {
        (set -e
                tmpfile_unsetvars=${TMPDIR}/conf_manipulate_available_var_defs::unsetvars.sh
-               _CONFVARS='ENV ALT_MOVED HOLD TABOO NOPKG REPLACE_FROM REPLACE_TO MARG_TARGET MARG_DEF MENV_TARGET MENV_DEF BEFOREBUILD BEFOREDEINSTALL AFTERINSTALL'
+               _CONFVARS='ENV ALT_MOVED HOLD TABOO FREEZE NOPKG REPLACE_FROM REPLACE_TO CONFLICT_TARGET CONFLICT_DEF MARG_TARGET MARG_DEF MENV_TARGET MENV_DEF BEFOREBUILD BEFOREDEINSTALL AFTERINSTALL'
                for item in ${_CONFVARS}
                do
                        misc_get_all_vardefs | grep -e "^${item}_" | cut -d = -f 1 | sed 's/^/unset /'
@@ -254,35 +254,34 @@ conf_build_replacement_patterns_from_REPLACE ()
 {
        local tmp_evaluated_origins
        tmp_matching_origins=${TMPDIR}/conf_build_replacement_patterns_from_REPLACE:origins
-       cp /dev/null "${DBDIR}/conf/REPLACE.grep_from_pattern"
+       cp /dev/null "${DBDIR}/conf/REPLACE.filter"
        cp /dev/null "${DBDIR}/conf/REPLACE.sed_pattern"
        cp /dev/null "${DBDIR}/conf/REPLACE.csv"
        misc_get_all_vardefs | grep -e '^_CONF_REPLACE_FROM_' | cut -d = -f 1 | while read var
        do
                eval glob_pattern=\$\{$var\}
                eval to=\$\{`echo "$var" | sed 's/^_CONF_REPLACE_FROM_/_CONF_REPLACE_TO_/'`\}
-               pkgsys_eval_ports_glob_even_if_nonexistent "$glob_pattern" > $tmp_matching_origins || :
-               if [ `wc -l < $tmp_matching_origins` -eq 0 ]
+               pkgsys_eval_ports_glob_even_if_nonexistent "$glob_pattern" > ${DBDIR}/conf/REPLACE.filter || :
+               if [ `wc -l < ${DBDIR}/conf/REPLACE.filter` -eq 0 ]
                then
                        message_echo "WARNING: Original package to be replaced [$glob_pattern] is obsolete." >&2
-                       message_echo "If still required, use a pattern for port origins instead." >&2
+                       message_echo "If still required, use a pattern for flavored port origins instead." >&2
                        continue
                fi
-               str_escape_regexp_filter < $tmp_matching_origins \
-                       | sed 's|^|^|; s|$|$|' >> ${DBDIR}/conf/REPLACE.grep_from_pattern
                if [ -z "$to" -o "$to" = delete ]
                then
                        to=
                else
-                       [ -d "${PORTSDIR}/$to" ] || message_echo "WARNING: replacement port [$to] is obsolete." >&2
+                       to_port_path=`pkgsys_get_portpath_from_origin "$to"`
+                       [ -d "$to_port_path" ] || message_echo "WARNING: replacement port [$to] is obsolete." >&2
                fi
-               str_escape_regexp_filter < $tmp_matching_origins \
+               str_escape_regexp_filter < ${DBDIR}/conf/REPLACE.filter \
                        | sed -E "s|^|s:^|; s/$/$:`str_escape_replaceval \"$to\"`:/" \
                        >> ${DBDIR}/conf/REPLACE.sed_pattern
                while read from
                do
                        printf '%s\t%s\n' "$from" "$to"
-               done < $tmp_matching_origins >> ${DBDIR}/conf/REPLACE.csv
+               done < ${DBDIR}/conf/REPLACE.filter >> ${DBDIR}/conf/REPLACE.csv
        done
 }
 
index 3715839..75c44c5 100644 (file)
@@ -2,94 +2,19 @@
 # ==============================================================================
 # portsreinstall library script
 # - Operations for building the temporary database -
-# Copyright (C) 2013-2017 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# Copyright (C) 2013-2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
 # This software is distributed under the 2-Clause BSD License.
 # ==============================================================================
 
-# ============= Variables =============
-DATABASE_VERSION=
-DATABASE_IS_OBSOLETE=no
-
-# ============= Creation =============
-database_build_create ()
-{
-       [ `id -u` -eq 0 -a ! -d "${DBDIR}" ] && mkdir -p "${DBDIR}"
-       misc_lock_duplicated_executions "${DBDIR}/.lock"
-       if [ -e "${DBDIR}/MYVERSION" ]
-       then
-               if ! grep -q -E "$COMPATIBLE_VERSIONS" "${DBDIR}/MYVERSION" 2> /dev/null
-               then
-                       message_echo "ERROR: The current temporary database is incompatible. You must delete it by" >&2
-                       message_echo "        ${APPNAME} clean force" >&2
-                       message_echo "       in order to enable the current version." >&2
-                       exit 1
-               fi
-       elif misc_is_superuser_privilege
-       then
-               echo "$MYVERSION" > ${DBDIR}/MYVERSION
-       fi
-       DATABASE_VERSION=`cat "${DBDIR}"/MYVERSION 2> /dev/null || :`
-       misc_is_superuser_privilege || return 0
-       for subdir in initial requires replace targets obsolete backup_packages \
-               stage.loop_list stage.complete stage.reinit_loop stage.depends
-       do
-               [ -d "${DBDIR}/$subdir" ] || mkdir -p "${DBDIR}/$subdir"
-       done
-}
-
-# ============= Refresh the temporary database =============
-database_build_refresh ()
-{
-       misc_is_superuser_privilege || return
-       [ $opt_suppress_obsolete_db_clean = no ] || return
-       message_echo "INFO: The temporary database is cleaned up."
-       message_echo
-       [ -d "${DBDIR}" -a ! -d "${DBDIR}.tmp" ] && mv "${DBDIR}" "${DBDIR}.tmp"
-       database_build_create
-       mv "${DBDIR}.tmp/saved_options.sh" "${DBDIR}" 2> /dev/null || :
-       mv "${DBDIR}.tmp/backup_packages" "${DBDIR}" 2> /dev/null || :
-       mv "${DBDIR}.tmp/backup_pkgarcs.lst" "${DBDIR}" 2> /dev/null || :
-       rm -rf "${DBDIR}.tmp"
-}
-
-# ============= Clean up the temporary database for upgrade of this utility =============
-database_build_clean_for_self_upgrade ()
-{
-       misc_is_superuser_privilege || return
-       [ $opt_suppress_obsolete_db_clean = no ] || return
-       rm -rf "${DBDIR}"
-       database_build_create
-       [ -e "${DBDIR}/MYVERSION" ] && mv "${DBDIR}/MYVERSION" "${DBDIR}/MYVERSION.prev"
-       :
-}
-
-# ============= Check whether the temporary database is newer than the ports tree and refresh if so =============
-database_build_refresh_if_obsolete ()
-{
-       if [ "${PORTS_INDEX_DB}" -nt "${DBDIR}"/MYVERSION ] && misc_is_superuser_privilege
-       then
-               if [ $opt_suppress_obsolete_db_clean = no -a "z${command}" = zclean ]
-               then
-                       DATABASE_IS_OBSOLETE=no
-                       message_echo "WARNING: The temporary database is older than the ports tree." >&2
-                       database_build_refresh || DATABASE_IS_OBSOLETE=yes
-               else
-                       DATABASE_IS_OBSOLETE=yes
-               fi
-       else
-               DATABASE_IS_OBSOLETE=no
-       fi
-}
-
-# ============= Register an obsolete origin =============
+# ============= Register an obsolete flavored origin =============
 database_build_register_obsolete_port ()
 {
        local origin dbpath pkgtag
        origin=$1
        dbpath=${DBDIR}/obsolete/$origin
        [ -e "$dbpath/complete_as_node" ] && return
-       [ -d "${DBDIR}/obsolete/$origin" ] || mkdir -p "${DBDIR}/obsolete/$origin"
-       pkgtag=`pkgsys_pkg_info_qO_init "$origin"`
+       mkdir -p "${DBDIR}/obsolete/$origin"
+       pkgtag=`pkgsys_get_init_pkg_from_orig "$origin"`
        [ -n "$pkgtag" ] || pkgtag='[not installed]'
        echo "$pkgtag" > ${DBDIR}/obsolete/$origin/pkgtag
        for table in dependents requirements
@@ -106,7 +31,7 @@ database_build_register_obsolete_port ()
        touch "$dbpath/complete_as_node"
 }
 
-# ============= Convert and register if an origin is obsolete =============
+# ============= Convert and register if a flavored origin is obsolete =============
 database_build_convert_and_register_origin_if_obsolete ()
 {
        local origin recursedb_in recursedb output_origin iline_db origin_new date_moved why_moved
@@ -114,7 +39,7 @@ database_build_convert_and_register_origin_if_obsolete ()
        recursedb_in=$2
        recursedb=${recursedb_in:-${PORTS_MOVED_DB}}
        echo "$origin" > ${TMPDIR}/database_build_convert_and_register_origin_if_obsolete:origin
-       [ -d "${PORTSDIR}/$origin" ] && return
+       pkgsys_exists_port "$origin" && return
        database_build_register_obsolete_port "$origin"
        grep -n -m 1 -E "^`str_escape_regexp \"$origin\"`\|" "$recursedb" 2> /dev/null > ${TMPDIR}/moved.info || :
        if [ `wc -l < ${TMPDIR}/moved.info` -eq 0 ]
@@ -136,6 +61,7 @@ database_build_convert_and_register_origin_if_obsolete ()
                if [ -n "$origin_new" ]
                then
                        message_echo "${DEPTH_INDEX}  ===> Moved to $origin_new at $date_moved because \"$why_moved\""
+                       fileedit_add_a_line_if_new "$origin" "${TMPDIR}/database_build_convert_and_register_origin_if_obsolete:origins_old"
                        database_build_convert_and_register_origin_if_obsolete "$origin_new" "${TMPDIR}/MOVED.DB" || return 1
                else
                        message_echo "${DEPTH_INDEX}  ===> Deleted at $date_moved because \"$why_moved\""
@@ -144,12 +70,25 @@ database_build_convert_and_register_origin_if_obsolete ()
                fi
        fi
 }
-# ============= [Sub-function] Get the output value of converted origin =============
-_database_build_convert_and_register_origin_if_obsolete__get_origin ()
+
+# ============= [Sub-function] Get the true latest flavored origin =============
+database_build_convert_and_register_origin_if_obsolete__get_origin ()
 {
        cat "${TMPDIR}/database_build_convert_and_register_origin_if_obsolete:origin"
 }
 
+# ============= [Sub-function] Reset the all old origins of the tested flavored origin =============
+database_build_convert_and_register_origin_if_obsolete__reset_origins_old ()
+{
+       rm -rf "${TMPDIR}/database_build_convert_and_register_origin_if_obsolete:origins_old"
+}
+
+# ============= [Sub-function] Save the all old origins of the tested flavored origin =============
+database_build_convert_and_register_origin_if_obsolete__save_origins_old ()
+{
+       cat "${TMPDIR}/database_build_convert_and_register_origin_if_obsolete:origins_old" 2> /dev/null
+}
+
 # ============= Get the make arguments for building the temporary database =============
 database_build_setup_make_args ()
 {
@@ -173,6 +112,8 @@ database_build_setup_make_args ()
                dbdir=${DBDIR}/requires/$origin
                [ -d "$dbdir" ] || dbdir=${DBDIR}/conf/each_port/$origin
                cat "$dbdir/MARG.conf" 2> /dev/null || :
+               flavor=`pkgsys_get_flavor_from_origin "$origin"`
+               [ -z "$flavor" ] || echo "FLAVOR=$flavor"
        } | tr '\n' ' '
 }
 
@@ -189,12 +130,13 @@ database_build_setup_make_envs ()
 # ============= Execute make command for building the temporary database =============
 database_build_make ()
 {
-       local origin MAKE_ARGS MAKE_ENVS
+       local origin MAKE_ARGS MAKE_ENVS port_path flavor
        origin=$1
        shift
        MAKE_ARGS=`database_build_setup_make_args "$origin"`
        MAKE_ENVS=`database_build_setup_make_envs "$origin"`
-       env $MAKE_ENVS make -C "${PORTSDIR}/$origin" "$@" $MAKE_ARGS
+       port_path=`pkgsys_get_portpath_from_origin "$origin"`
+       env $MAKE_ENVS make -C "$port_path" "$@" $MAKE_ARGS
 }
 
 # ============= Set up a temporary database node for the initial state of a port =============
@@ -206,7 +148,7 @@ database_build_setup_initial_node ()
        [ -e "$dbpath/complete_as_node" ] && return
        rm -rf "$dbpath"
        mkdir -p "$dbpath"
-       pkg=`pkg_info_qO "$origin"`
+       pkg=`pkgsys_get_installed_pkg_from_origin "$origin"`
        if [ -n "$pkg" ]
        then
                echo "$pkg" > $dbpath/installed_version
@@ -248,48 +190,61 @@ database_build_setup_initial_node ()
 # ============= Set up a temporary database node for the replaced/moved information of a port =============
 database_build_setup_replace_node ()
 {
-       local origin_orig origin dbpath
+       local origin_orig origin_trial origin dbpath
        origin_orig=$1
        dbpath=${DBDIR}/replace/$origin_orig
        if [ ! -e "$dbpath/complete_as_node" ]
        then
                rm -rf "$dbpath"
                mkdir -p "$dbpath"
-               origin=$origin_orig
-               if echo "$origin_orig" | grep -q -E -f "${DBDIR}/conf/REPLACE.grep_from_pattern"
+               origin_trial=$origin_orig
+               if echo "$origin_orig" | grep -q -Fx -f "${DBDIR}/conf/REPLACE.filter" 2> /dev/null
                then
-                       origin=`echo "$origin_orig" | sed -E -f "${DBDIR}/conf/REPLACE.sed_pattern"`
-                       if [ "x$origin_orig" != "x$origin" ]
+                       origin_trial=`echo "$origin_orig" | sed -E -f "${DBDIR}/conf/REPLACE.sed_pattern"`
+                       if [ "x$origin_orig" != "x$origin_trial" ]
                        then
-                               if [ -n "$origin" ]
+                               if [ -n "$origin_trial" ]
                                then
-                                       message_echo "${DEPTH_INDEX}  ===> Replaced with $origin by user configuration"
+                                       message_echo "${DEPTH_INDEX}  ===> Replaced with $origin_trial by user configuration"
                                else
                                        database_build_register_obsolete_port "$origin_orig"
                                        message_echo "${DEPTH_INDEX}  ===> Deleted by user configuration"
                                fi > $dbpath/message
                        fi
                fi
-               if [ -n "$origin" ]
+               if [ -n "$origin_trial" ]
                then
-                       if database_build_convert_and_register_origin_if_obsolete "$origin" >> $dbpath/message
+                       if database_build_convert_and_register_origin_if_obsolete "$origin_trial" >> $dbpath/message
                        then
-                               origin=`_database_build_convert_and_register_origin_if_obsolete__get_origin`
+                               origin_trial=`database_build_convert_and_register_origin_if_obsolete__get_origin`
                        else
-                               if [ "x$origin" != "x$origin_orig" ]
+                               if [ "x$origin_trial" != "x$origin_orig" ]
                                then
                                        message_echo "${DEPTH_INDEX}  ===> Going back to the original port $origin_orig"
                                        if database_build_convert_and_register_origin_if_obsolete "$origin_orig"
                                        then
-                                               origin=`_database_build_convert_and_register_origin_if_obsolete__get_origin`
+                                               origin_trial=`database_build_convert_and_register_origin_if_obsolete__get_origin`
                                        else
-                                               origin=
+                                               origin_trial=
                                        fi
                                else
-                                       origin=
+                                       origin_trial=
                                fi >> $dbpath/message
                        fi
                fi
+               # Configure the port option to determine the true flavor
+               database_build_determine_port_option "$origin_trial"
+               # Get the true flavor to determine the flavored port origin
+               origin=`database_build_determine_flavored_origin "$origin_trial"`
+               if [ "x$origin_trial" != "x$origin" ]
+               then
+                       if [ -n "$origin" ]
+                       then
+                               message_echo "${DEPTH_INDEX}  ===> Transferred to $origin"
+                       else
+                               message_echo "${DEPTH_INDEX}  ===> Lost (Something is wrong!)"
+                       fi
+               fi
                [ "x$origin_orig" = "x$origin" ] || echo "$origin" > $dbpath/origin
                touch "$dbpath/complete_as_node"
        fi
@@ -299,18 +254,16 @@ database_build_setup_replace_node ()
 # ============= Get the inspected level for a port with the current option settings =============
 database_build_get_inspected_level ()
 {
-       local origin origin_dependent origin_esc origin_dependent_esc
+       local origin origin_dependent
        origin=$1
        origin_dependent=$2
-       origin_esc='^'`str_escape_regexp "$origin"`'$'
-       origin_dependent_esc='^'`str_escape_regexp "$origin_dependent"`'$'
        if [ $opt_only_target_scope = no ]
        then
                echo full
-       elif ! pkgsys_pkg_info_eO "$origin" \
-               || grep -E "$origin_esc" "${DBDIR}/stage.loop_list/ports_to_inspect" > /dev/null \
-               || [ ! -e "${DBDIR}/requires/$origin_dependent/installed_version" ] \
-               || grep -E "$origin_dependent_esc" "${DBDIR}/stage.loop_list/ports_to_inspect" > /dev/null
+       elif ! pkgsys_exists_or_existed_from_orig "$origin" \
+               || grep -qFx "$origin" "${DBDIR}/stage.loop_list/ports_to_inspect" 2> /dev/null \
+               || [ ! -e "${DBDIR}/moved_from/$origin_dependent/installed_version" ] \
+               || grep -qFx "$origin_dependent" "${DBDIR}/stage.loop_list/ports_to_inspect" 2> /dev/null
        then
                echo direct
        else
@@ -321,46 +274,39 @@ database_build_get_inspected_level ()
 # ============= Check whether a port has been inspected in a required level =============
 database_build_is_port_already_inspected_in_required_level ()
 {
-       local origin origin_dependent origin_actual origin_esc inspected_level
+       local origin origin_dependent origin_actual inspected_level
        origin=$1
        origin_dependent=$2
        origin_actual=`echo "$origin" | sed -E -f "${DBDIR}/REPLACE.complete_sed_pattern" 2> /dev/null || :`
        [ -n "$origin_actual" ] || origin_actual=$origin
-       origin_esc='^'`str_escape_regexp "$origin_actual"`'$'
        inspected_level=`database_build_get_inspected_level "$origin_actual" "$origin_dependent"`
-       grep -q -E "^$origin_esc$" "${DBDIR}/ports.inspected.${inspected_level}.list" \
+       grep -q -Fx "$origin_actual" "${DBDIR}/ports.inspected.${inspected_level}.list" \
                "${DBDIR}/obsolete_ports" 2> /dev/null || return
        fileedit_rm_a_line "$origin" "${DBDIR}/stage.loop_list/ports_to_inspect.remain"
        [ "x$origin" = "$origin_actual" ] || \
                fileedit_rm_a_line "$origin_actual" "${DBDIR}/stage.loop_list/ports_to_inspect.remain"
-       :
+       echo "$origin_actual"
 }
 
 # ============= Update the current package name of a port =============
 database_build_update_pkgname ()
 {
-       local origin pkg savefile origin_orig
+       local origin dbdir pkg savefile
        origin=$1
-       savefile=${DBDIR}/requires/$origin/current_version
-       if [ -e "${DBDIR}/REVERSE_REPLACE.complete_sed_pattern" ]
+       dbdir=${DBDIR}/moved_from/$origin
+       mkdir -p "$dbdir"
+       savefile=$dbdir/current_version
+       pkg=`pkgsys_get_installed_pkg_from_origin "$origin"`
+       if [ -z "$pkg" -a -e "$dbdir/initial_orig" ]
        then
-               origin_orig=`echo "$origin" \
-                       | sed -E -f "${DBDIR}/REVERSE_REPLACE.complete_sed_pattern"` || :
-               [ "x$origin_orig" = "x$origin" ] && origin_orig=
-       else
-               origin_orig=
-       fi
-       echo "$origin_orig" "$origin" | tr ' ' '\n' | grep -v '^$' | while read orig
-       do
-               pkg=`pkg_info_qO "$orig" || :`
-               if [ -z "$pkg" -a -e "${DBDIR}/requires/$orig/initial_orig" ]
-               then
-                       orig_init=`cat "${DBDIR}/requires/$orig/initial_orig"`
-                       pkg=`pkg_info_qO "$orig_init" || :`
-               fi
-               [ -n "$pkg" ] && echo "$pkg"
-               :
-       done | sort -u > $savefile
+               while read orig_init
+               do
+                       pkgsys_get_installed_pkg_from_origin "$orig_init"
+               done < $dbdir/initial_orig
+       elif [ -n "$pkg" ]
+       then
+               echo "$pkg"
+       fi | sort -u > $savefile
        cat "$savefile"
 }
 
@@ -369,7 +315,7 @@ database_build_get_pkgname ()
 {
        local origin savefile
        origin=$1
-       savefile=${DBDIR}/requires/$origin/current_version
+       savefile=${DBDIR}/moved_from/$origin/current_version
        if [ -e "$savefile" ]
        then
                cat "$savefile"
@@ -381,7 +327,7 @@ database_build_get_pkgname ()
 # ============= Get the new package name of a port =============
 database_build_get_new_pkgname ()
 {
-       local origin savefile pkg
+       local origin savefile
        origin=$1
        savefile=${DBDIR}/requires/$origin/new_version
        if [ ! -e "$savefile" ]
@@ -392,12 +338,33 @@ database_build_get_new_pkgname ()
        cat "$savefile"
 }
 
+# ============= Get the package list of full-run-time requirements =============
+database_build_get_full_run_requirement_pkgs ()
+{
+       local origin srcfile savefile
+       origin=$1
+       srcfile=${DBDIR}/requires/$origin/requirements.run.full
+       savefile=${DBDIR}/requires/$origin/pkg_requirements.run.full
+       if [ ! -e "$srcfile" ]
+       then
+               rm -f "$savefile"
+       elif [ ! -e "$savefile" -o "$savefile" -ot "$srcfile" ]
+       then
+               while read origin
+               do
+                       database_build_get_new_pkgname "$origin"
+               done < $srcfile | grep -v '^[[:space:]]*$' | sort -u > $savefile
+       fi
+       cat "$savefile" 2> /dev/null || :
+}
+
 # ============= Build the original message tag showing the version upgrade =============
 database_build_create_pkgtag ()
 {
        local origin dbdir pkg_init pkg_new pkgtag
        origin=$1
-       dbdir=${DBDIR}/requires/$origin
+       dbdir=${DBDIR}/moved_from/$origin
+       mkdir -p "$dbdir"
        pkg_init=`database_build_get_pkgname "$origin"`
        [ -n "$pkg_init" -a ! -e "$dbdir/installed_version" ] && \
                echo -n "$pkg_init" > $dbdir/installed_version
@@ -424,10 +391,12 @@ database_build_create_pkgtag ()
 # ============= Update the message tag showing the version upgrade =============
 database_build_update_pkgtag ()
 {
-       local origin pkg_init pkg_bak pkg_cur detail pkgtag
+       local origin dbdir pkg_init pkg_bak pkg_cur detail pkgtag
        origin=$1
-       pkg_init=`cat "${DBDIR}/requires/$origin/installed_version" 2> /dev/null | tr '\n' ' ' | sed 's/ *$//'`
-       pkg_bak=`cat "${DBDIR}/requires/$origin/backedup_version" 2> /dev/null | tr '\n' ' ' | sed 's/ *$//'`
+       dbdir=${DBDIR}/moved_from/$origin
+       mkdir -p "$dbdir"
+       pkg_init=`cat "$dbdir/installed_version" 2> /dev/null | tr '\n' ' ' | sed 's/ *$//'`
+       pkg_bak=`cat "$dbdir/backedup_version" 2> /dev/null | tr '\n' ' ' | sed 's/ *$//'`
        pkg_cur=`database_build_get_pkgname "$origin" | tr '\n' ' ' | sed 's/ *$//'`
        detail=
        if [ "x$pkg_init" != "x$pkg_cur" ]
@@ -442,8 +411,8 @@ database_build_update_pkgtag ()
                        detail=" [currently deinstalled]"
                fi
        fi
-       pkgtag=`cat "${DBDIR}/requires/$origin/pkgtag.orig"`
-       echo "$pkgtag$detail" > ${DBDIR}/requires/$origin/pkgtag
+       pkgtag=`cat "$dbdir/pkgtag.orig"`
+       echo "$pkgtag$detail" > $dbdir/pkgtag
 }
 
 # ============= Check whether the currently installed package version is the latest =============
@@ -455,188 +424,389 @@ database_build_is_currentpkg_latest ()
        pkg_new=`database_build_get_new_pkgname "$origin"`
        [ "x$pkg_cur" = "x$pkg_new" ]
 }
+# ============= Configure the port option to determine the true flavor =============
+database_build_determine_port_option ()
+{
+       local origin
+       origin=$1
+       if [ $opt_apply_default_config = yes ]
+       then
+               if ! pkgsys_is_dialog4ports_used
+               then
+                       printf '\t\n' | database_build_make "$origin" config-conditional > /dev/null
+               fi
+       else
+               database_build_make "$origin" config-conditional
+       fi
+}
+
+# ============= Get the true flavor to determine the flavored port origin =============
+database_build_determine_flavored_origin ()
+{
+       local origin origin_unflavored flavor_trial flavor
+       origin=$1
+       origin_unflavored=`pkgsys_get_unflavored_origin "$origin"`
+       flavor_trial=`pkgsys_get_flavor_from_origin "$origin"`
+       if [ -n "$flavor_trial" ]
+       then
+               flavors_ptn="^("`database_build_make "$origin" -V FLAVORS 2> /dev/null | sed -E 's/[[:space:]]+/|/g'`")$"
+               echo "$flavor_trial" | grep -qE "$flavors_ptn" || origin_trial=$origin_unflavored
+       fi
+       flavor=`database_build_make "$origin" -V FLAVOR 2> /dev/null || :`
+       pkgsys_compose_flavored_origin "$origin_unflavored" "$flavor"
+}
+
+# ============= Escape of inspection conflict =============
+database_build_escape_inspect_conflict ()
+{
+       local origin dbpath
+       dbpath=${DBDIR}/requires/$origin
+       if [ -e "$dbpath/CONFLICT.conf" ]
+       then
+               message_echo "${DEPTH_INDEX}  ===> Escaping inspection conflict..."
+               pkgsys_eval_ports_glob `cat "$dbpath/CONFLICT.conf"` | while read origin_conflict
+               do
+                       pkg_conflict=`pkgsys_get_installed_pkg_from_origin "$origin_conflict"`
+                       [ -n "$pkg_conflict" ] || continue
+                       message_echo "${DEPTH_INDEX}  ===> Escaping $pkg_conflict..."
+                       pkgarc=`pkgsys_create_backup_pkg "$pkg_conflict" "${DBDIR}/backup_packages" 2> /dev/null` || \
+                               message_echo "${DEPTH_INDEX}  ===> (WARNING: Failed to back up)"
+                       pkg_delete_f "$pkg_conflict" > /dev/null 2>&1 || \
+                               message_echo "${DEPTH_INDEX}  ===> (WARNING: Failed to delete)"
+                       [ -n "$pkgarc" ] && printf '%s\t%s\n' "$pkg_conflict" "$pkgarc" >> $dbpath/CONFLICT_pkgarc.lst
+               done
+       fi
+}
+
+# ============= Restoration of escaped inspection conflict =============
+database_build_restore_inspect_conflict ()
+{
+       local origin dbpath
+       dbpath=${DBDIR}/requires/$origin
+       if [ -e "$dbpath/CONFLICT.conf" ]
+       then
+               message_echo "${DEPTH_INDEX}  ===> Restoring inspection conflict..."
+               cat "$dbpath/CONFLICT_pkgarc.lst" 2> /dev/null | while read pkg_conflict pkgarc
+               do
+                       pkg_info_e "$pkg_conflict" && continue
+                       message_echo "${DEPTH_INDEX}  ===> Restoring $pkg_conflict..."
+                       pkg_add_f "$pkgarc" > /dev/null 2>&1 || \
+                               message_echo "${DEPTH_INDEX}  ===> (WARNING: Failed to restore $pkg_conflict)"
+               done
+               rm -f "$dbpath/CONFLICT_pkgarc.lst"
+       fi
+}
 
 # ============= Recursively inspect dependencies of a port and build a node database of the information =============
 database_build_inspect_dependencies ()
 {
-       local origin_orig origin_dependent origin_orig_regexp origin origin_regexp tag stage dbpath origin_id origin_dependency DEPTH_INDEX_orig nlines iline dist_subdir_rpl inspected_level inspected_levels_compatible origin_tmp inspected_level_tmp conf_updated tmp_portsdb_work tmp_portopt
+       local origin_orig origin_dependent origin_orig_regexp origin_replace origin_trial origin tag stage level dbpath dbpath_prev origin_id tmp_config origin_dependency DEPTH_INDEX_orig nlines iline dist_subdir_rpl inspected_level inspected_levels_compatible origin_tmp inspected_level_tmp conf_updated tmp_portsdb_work tmp_portopt same_as_prevset dbfile installed_version frompath variable pkg_new
        origin_orig=$1
        origin_dependent=$2
        [ -z "$origin_orig" ] && return
-       database_build_is_port_already_inspected_in_required_level "$origin_orig" "$origin_dependent" && return
-       origin_orig_regexp=`str_escape_regexp "$origin_orig"`
-       DEPTH_INDEX_orig=${DEPTH_INDEX}
-       DEPTH_INDEX="${DEPTH_INDEX}--"
-       message_echo "${DEPTH_INDEX} $origin_orig"
-       origin_id=`echo "$origin_orig" | tr / :`
-       database_build_setup_initial_node "$origin_orig"
-       database_build_setup_replace_node "$origin_orig"
-       if [ -e "${DBDIR}/replace/$origin_orig/origin" ]
-       then
-               origin=`cat "${DBDIR}/replace/$origin_orig/origin"`
-       else
-               origin=$origin_orig
-       fi
-       origin_regexp=`str_escape_regexp "$origin"`
-       inspected_level=
-       inspected_levels_compatible=
-       if [ -n "$origin" ]
+       if ! origin=`database_build_is_port_already_inspected_in_required_level "$origin_orig" "$origin_dependent"`
        then
-               fileedit_rm_a_line "$origin" "${DBDIR}/obsolete_ports"
-               dbpath=${DBDIR}/requires/$origin
-               if [ ! -e "$dbpath/complete_as_node" ]
+               DEPTH_INDEX_orig=${DEPTH_INDEX}
+               DEPTH_INDEX="${DEPTH_INDEX}--"
+               message_echo "${DEPTH_INDEX} $origin_orig"
+               database_build_convert_and_register_origin_if_obsolete__reset_origins_old
+               origin_id=`echo "$origin_orig" | tr / :`
+               database_build_setup_initial_node "$origin_orig"
+               # Replacement specified by the configuration file, knobs and port options
+               tmp_config=${TMPDIR}/database_build_inspect_dependencies:confi
+               database_build_make "$origin_trial" showconfig > $tmp_config.before 2> /dev/null || :
+               database_build_setup_replace_node "$origin_orig"
+               database_build_make "$origin_trial" showconfig > $tmp_config.after 2> /dev/null || :
+               if [ -e "${DBDIR}/replace/$origin_orig/origin" ]
                then
-                       conf_updated=
-                       if grep -q -E -e "^$origin_orig_regexp$" -e "^$origin_regexp$" "${DBDIR}/to_be_reconf" 2> /dev/null
-                       then
-                               message_echo "${DEPTH_INDEX}  ===> Reconfigured"
-                               conf_updated=y
-                       fi
-                       rm -rf "$dbpath"
-                       mkdir -p "$dbpath"
-                       [ -n "$conf_updated" ] && touch "$dbpath/conf_updated"
-                       [ "x$origin_orig" = "x$origin" ] || echo "$origin_orig" > $dbpath/initial_orig
-                       [ -e "${DBDIR}/initial/$origin_orig/SUPPRESSED_SELF" ] && touch "$dbpath/SUPPRESSED_SELF"
-                       [ -e "${DBDIR}/initial/$origin_orig/SUPPRESSED_PKGNG" ] && touch "$dbpath/SUPPRESSED_PKGNG"
-                       if [ -d "${DBDIR}/conf/each_port/$origin" ]
+                       origin=`cat "${DBDIR}/replace/$origin_orig/origin"`
+               else
+                       origin=$origin_orig
+               fi
+               # Build the database for this port
+               inspected_level=
+               inspected_levels_compatible=
+               if [ -n "$origin" ]
+               then
+                       frompath=${DBDIR}/moved_from/$origin
+                       mkdir -p "$frompath"
+                       database_build_convert_and_register_origin_if_obsolete__save_origins_old | \
+                               fileedit_add_lines_if_new "$frompath/old_origs"
+                       # Check the package name initially installed
+                       installed_version=`cat "${DBDIR}/initial/$origin_orig/installed_version" 2> /dev/null || :`
+                       [ -n "$installed_version" ] && fileedit_add_a_line_if_new "$installed_version" "$frompath/installed_version"
+                       [ "x$origin_orig" = "x$origin" ] || fileedit_add_a_line_if_new "$origin_orig" "$frompath/initial_orig"
+                       [ -e "${DBDIR}/initial/$origin_orig/SUPPRESSED_SELF" ] && touch "$frompath/SUPPRESSED_SELF"
+                       [ -e "${DBDIR}/initial/$origin_orig/SUPPRESSED_PKGNG" ] && touch "$frompath/SUPPRESSED_PKGNG"
+                       if ! grep -qFx "$origin" "${DBDIR}/done_required_ports_to_inspect" 2> /dev/null
                        then
-                               cp -R "${DBDIR}/conf/each_port/$origin/"* "$dbpath/" > /dev/null 2>&1 || :
-                       fi
-                       tmp_portsdb_work=${TMPDIR}/database_build_inspect_dependencies:portsdb_work
-                       tmp_portopt=${TMPDIR}/database_build_inspect_dependencies:portopt
-                       [ -d "$tmp_portsdb_work" ] || mkdir "$tmp_portsdb_work"
-                       ( set -e
-                               export PORT_DBDIR=$tmp_portsdb_work
-                               export __MAKE_CONF=
-                               if database_build_make "$origin" showconfig > $tmp_portopt
+                               fileedit_rm_a_line "$origin" "${DBDIR}/obsolete_ports"
+                               dbpath=${DBDIR}/requires/$origin
+                               dbpath_prev=${DBDIR}/prevset/requires/$origin
+                               if [ ! -e "$dbpath/complete_as_node" ] || \
+                                       ! diff "$tmp_config.before" "$tmp_config.after" > /dev/null 2> /dev/null
                                then
-                                       cp "$tmp_portopt" "$dbpath"/ports_options.default
+                                       # Notify reconfiguration of the port option
+                                       conf_updated=
+                                       if [ -e "$dbpath/complete_as_node" ] || \
+                                               grep -q -Fx -e "$origin_orig" -e "$origin" "${DBDIR}/to_be_reconf" 2> /dev/null
+                                       then
+                                               message_echo "${DEPTH_INDEX}  ===> Reconfigured"
+                                               conf_updated=y
+                                       fi
+                                       # Reset the database
+                                       rm -rf "$dbpath"
+                                       mkdir -p "$dbpath"
+                                       [ -n "$conf_updated" ] && touch "$dbpath/conf_updated"
+                                       if [ -d "${DBDIR}/conf/each_port/$origin" ]
+                                       then
+                                               cp -R "${DBDIR}/conf/each_port/$origin/"* "$dbpath/" > /dev/null 2>&1 || :
+                                       fi
+                                       # Escape of inspection conflict
+                                       database_build_escape_inspect_conflict "$origin"
+                                       # Check the change of the port option from the default
+                                       tmp_portsdb_work=${TMPDIR}/database_build_inspect_dependencies:portsdb_work
+                                       tmp_portopt=${TMPDIR}/database_build_inspect_dependencies:portopt
+                                       [ -d "$tmp_portsdb_work" ] || mkdir "$tmp_portsdb_work"
+                                       ( set -e
+                                               export PORT_DBDIR=$tmp_portsdb_work
+                                               export __MAKE_CONF=
+                                               if database_build_make "$origin" showconfig > $tmp_portopt
+                                               then
+                                                       cp "$tmp_portopt" "$dbpath"/ports_options.default
+                                               else
+                                                       cat "$tmp_portopt" >&2
+                                                       message_echo 'Error in detecting the default options.' 2>&1
+                                                       exit 1
+                                               fi
+                                       )
+                                       if [ `wc -c < $dbpath/ports_options.default` -gt 0 ]
+                                       then
+                                               if database_build_make "$origin" showconfig > $tmp_portopt
+                                               then
+                                                       cp "$tmp_portopt" "$dbpath"/ports_options.current
+                                               else
+                                                       cat "$tmp_portopt" >&2
+                                                       message_echo 'Error in detecting the current options.' 2>&1
+                                                       exit 1
+                                               fi
+                                       else
+                                               cp /dev/null "$dbpath/ports_options.current"
+                                       fi
+                                       pkgsys_save_port_oprion_timestamp "$origin"
+                                       # Get the lists of requirements in the flavored form
+                                       database_build_create_pkgtag "$origin"
+                                       for variable in PKG_DEPENDS EXTRACT_DEPENDS PATCH_DEPENDS FETCH_DEPENDS BUILD_DEPENDS LIB_DEPENDS
+                                       do
+                                               database_build_make "$origin" -V $variable
+                                       done > ${TMPDIR}/database_build_inspect_dependencies:build_depends_list
+                                       for variable in LIB_DEPENDS RUN_DEPENDS
+                                       do
+                                               database_build_make "$origin" -V $variable
+                                       done > ${TMPDIR}/database_build_inspect_dependencies:run_depends_list
+                                       for tag in run build
+                                       do
+                                               tr ' ' '\n' < ${TMPDIR}/database_build_inspect_dependencies:${tag}_depends_list | \
+                                                       sed -E 's#.*:([^:/]+/[^:/]+|[^:/]+/[^:/]+:[^:/]*)$#\1#' | cut -d : -f 1 | sort -u | \
+                                                       grep -Ev "`pkgsys_pkgtools_ports_filter_regexp`" \
+                                                               | while read origin_flavor_incomplete
+                                                               do
+                                                                       ( set -e
+                                                                               opt_apply_default_config=yes
+                                                                               database_build_determine_port_option "$origin_flavor_incomplete"
+                                                                       )
+                                                                       database_build_determine_flavored_origin "$origin_flavor_incomplete"
+                                                               done | grep -v '^$' | sort -u > $dbpath/requirements.$tag.orig || :
+                                               sed -E -f "${DBDIR}/conf/REPLACE.sed_pattern" "$dbpath/requirements.$tag.orig" \
+                                                       | grep -v '^$' | sort -u > $dbpath/requirements.$tag.src || :
+                                       done
+                                       for stage in orig src
+                                       do
+                                               sort -u "$dbpath/requirements.run.${stage}" "$dbpath/requirements.build.${stage}" \
+                                                       > $dbpath/requirements.all.direct.${stage}
+                                               mv "$dbpath/requirements.build.${stage}" "$dbpath/requirements.build.direct.${stage}"
+                                               mv "$dbpath/requirements.run.${stage}" "$dbpath/requirements.run.direct.${stage}"
+                                       done
+                                       # Record the completion
+                                       touch "$dbpath/complete_as_node"
+                                       fileedit_rm_a_line "$origin_orig" "${DBDIR}/to_be_reconf"
+                                       fileedit_rm_a_line "$origin" "${DBDIR}/to_be_reconf"
+                                       # Restoration of escaped inspection conflict
+                                       database_build_restore_inspect_conflict "$origin"
                                else
-                                       cat "$tmp_portopt" >&2
-                                       message_echo 'Error in detecting the default options.' 2>&1
-                                       exit 1
+                                       # Restoration of escaped inspection conflict
+                                       database_build_restore_inspect_conflict "$origin"
+                                       # Reset the complied lists of requirements
+                                       for level in direct full
+                                       do
+                                               for tag in run build
+                                               do
+                                                       rm -f "$dbpath/requirements.${tag}.${level}"
+                                               done
+                                       done
+                                       for origin_tmp in "$origin" "$origin_orig"
+                                       do
+                                               for inspected_level_tmp in full direct node
+                                               do
+                                                       fileedit_rm_a_line "$origin_tmp" "${DBDIR}/ports.inspected.${inspected_level_tmp}.list"
+                                               done
+                                       done
                                fi
-                       )
-                       if [ `wc -c < $dbpath/ports_options.default` -gt 0 ]
-                       then
-                               if [ $opt_apply_default_config = yes ]
+                               # Inspect the requirements
+                               inspected_level=`database_build_get_inspected_level "$origin" "$origin_dependent"`
+                               case $inspected_level in
+                               full )
+                                       grep -v -Fx -f "${DBDIR}/installed_ports" \
+                                               "$dbpath/requirements.all.direct.src" > ${TMPDIR}/missing.$origin_id || :
+                                       inspected_levels_compatible='full direct node'
+                                       ;;
+                               direct )
+                                       grep -v -Fx -f "${DBDIR}/installed_ports" \
+                                               "$dbpath/requirements.all.direct.src" > ${TMPDIR}/missing.$origin_id || :
+                                       inspected_levels_compatible='direct node'
+                                       ;;
+                               node )
+                                       cp /dev/null "${TMPDIR}/missing.$origin_id"
+                                       inspected_levels_compatible='node'
+                                       ;;
+                               esac
+                               rm -rf "$dbpath/rename_requirements.sed.pattern"
+                               nlines=`wc -l < ${TMPDIR}/missing.$origin_id`
+                               iline=1
+                               while [ $iline -le $nlines ]
+                               do
+                                       origin_dependency=`sed -n ${iline}p "${TMPDIR}/missing.$origin_id"`
+                                       iline=$(($iline+1))
+                                       grep -q -Fx "$origin_dependency" "${DBDIR}/ports.inspected.list" 2> /dev/null && \
+                                                       continue
+                                       database_build_inspect_dependencies "$origin_dependency" "$origin"
+                               done
+                               if [ -e "$dbpath/rename_requirements.sed.pattern" ]
                                then
-                                       if ! pkgsys_is_dialog4ports_used
+                                       for tag in run build all
+                                       do
+                                               sed -E -i .unrenamed -f "$dbpath/rename_requirements.sed.pattern" "$dbpath/requirements.${tag}.direct.src"
+                                       done
+                               fi 
+                               rm -f "${TMPDIR}/missing.$origin_id"
+                               # Inspect the distfiles
+                               dist_subdir_rpl=`database_query_get_makevar_val "$origin" DIST_SUBDIR | str_escape_replaceval_filter` || :
+                               [ -n "$dist_subdir_rpl" ] && dist_subdir_rpl="$dist_subdir_rpl\/"
+                               database_build_make "$origin" fetch-urlall-list \
+                                       | sed -E "s/.*\/([^\/]+)$/$dist_subdir_rpl\1/" \
+                                       | sort -u | fileedit_add_lines_if_new "${DBDIR}/distfiles.inspected"
+                               # Transfer data from the previous database if existent, successful and no change
+                               pkg_new=`cat "$dbpath/new_version"`
+                               if [ ! -e "$dbpath/conf_updated" -a -d "$dbpath_prev" ] && pkg_info_e "$pkg_new" 2> /dev/null && \
+                                       ! grep -qFx "$origin" "$dbpath_prev/to_be_reconf" 2> /dev/null
+                               then
+                                       same_as_prevset=yes
+                                       for dbfile in new_version CONFLICT.conf MARG.conf MENV.conf \
+                                               ports_options.default ports_options.current \
+                                               rename_requirements.sed.pattern \
+                                               requirements.run.direct.orig requirements.run.direct.src \
+                                               requirements.build.direct.orig requirements.build.direct.src
+                                       do
+                                               [ ! -e "$dbpath/$dbfile" -a ! -e "$dbpath_prev/$dbfile" ] && continue
+                                               if ! diff "$dbpath/$dbfile"  "$dbpath_prev/$dbfile" 2> /dev/null > /dev/null
+                                               then
+                                                       same_as_prevset=no
+                                                       break
+                                               fi
+                                       done
+                                       if [ $same_as_prevset = yes ]
                                        then
-                                               printf '\t\n' | database_build_make "$origin" config-conditional > /dev/null
+                                               nlines=`wc -l < $dbpath/requirements.all.direct.src`
+                                               iline=1
+                                               while [ $iline -le $nlines ]
+                                               do
+                                                       origin_dependency=`sed -n ${iline}p "$dbpath/requirements.all.direct.src"`
+                                                       iline=$(($iline+1))
+                                                       if [ ! -e "${DBDIR}/requires/$origin_dependency/same_as_prevset" ]
+                                                       then
+                                                               same_as_prevset=no
+                                                               break
+                                                       fi
+                                               done
+                                       fi
+                                       if [ $same_as_prevset = yes ]
+                                       then
+                                               for dbfile in failed.list damaged_package manually_done.list
+                                               do
+                                                       if grep -qFx "$origin" "${DBDIR}/prevset/$dbfile" 2> /dev/null
+                                                       then
+                                                               same_as_prevset=no
+                                                               break
+                                                       fi
+                                               done
+                                       fi
+                                       if [ $same_as_prevset = yes ]
+                                       then
+                                               rm -rf "$dbpath"
+                                               cp -Rp "$dbpath_prev" "$dbpath"
+                                               if [ -d "${DBDIR}/prevset/notes/$origin" ]
+                                               then
+                                                       rm -rf "${DBDIR}/notes/$origin"
+                                                       mkdir -p "${DBDIR}/notes"
+                                                       cp -Rp "${DBDIR}/prevset/notes/$origin" "${DBDIR}/notes/$origin"
+                                               fi
+                                               {
+                                                       for tag in all run build none
+                                                       do
+                                                               for level in full direct
+                                                               do
+                                                                       echo "success.$tag.$level.list"
+                                                               done
+                                                       done
+                                               } | while read dbfile
+                                               do
+                                                       if grep -Fxq "$origin" "${DBDIR}/prevset/$dbfile" 2> /dev/null
+                                                       then
+                                                               fileedit_add_a_line_if_new "$origin" "${DBDIR}/$dbfile"
+                                                       fi
+                                               done
+                                               touch "$dbpath/same_as_prevset"
+                                               message_echo "${DEPTH_INDEX}  ===> No update from the previous reinstallation. Progress status inherited."
                                        fi
-                               else
-                                       database_build_make "$origin" config-conditional
                                fi
-                               if database_build_make "$origin" showconfig > $tmp_portopt
+                               # Record the completion
+                               if [ "x$origin_orig" != "x$origin" ]
                                then
-                                       cp "$tmp_portopt" "$dbpath"/ports_options.current
-                               else
-                                       cat "$tmp_portopt" >&2
-                                       message_echo 'Error in detecting the current options.' 2>&1
-                                       exit 1
+                                       for inspected_level_tmp in $inspected_levels_compatible
+                                       do
+                                               fileedit_add_a_line_if_new "$origin" "${DBDIR}/ports.inspected.${inspected_level_tmp}.list"
+                                       done
+                                       fileedit_add_a_line_if_new "$origin" "${DBDIR}/ports.inspected.list"
+                                       fileedit_add_a_line_if_new "$origin" "${DBDIR}/inspected_ports.update"
+                                       fileedit_rm_a_line "$origin" "${DBDIR}/stage.loop_list/ports_to_inspect.remain"
                                fi
+                               fileedit_add_a_line_if_new "$origin" "${DBDIR}/done_required_ports_to_inspect"
                        else
-                               cp /dev/null "$dbpath/ports_options.current"
-                       fi
-                       if [ ! -e "${DBDIR}/initial/$origin_orig/installed_version" ]
-                       then
-                               cp "${DBDIR}/initial/$origin_orig/installed_version" "$dbpath" 2> /dev/null || :
-                       fi
-                       database_build_create_pkgtag "$origin"
-                       for tag in run build
-                       do
-                               database_build_make "$origin" $tag-depends-list \
-                                       | sed -E "s/^`str_escape_regexp "${PORTSDIR}"`\///" \
-                                       | grep -Ev "`pkgsys_pkgtools_ports_filter_regexp`" \
-                                       > $dbpath/requirements.$tag.orig || :
-                               sed -E -f "${DBDIR}/conf/REPLACE.sed_pattern" "$dbpath/requirements.$tag.orig" \
-                                       | grep -v '^$' > $dbpath/requirements.$tag.src || :
-                       done
-                       for stage in orig src
-                       do
-                               sort -u "$dbpath/requirements.run.${stage}" "$dbpath/requirements.build.${stage}" \
-                                       > $dbpath/requirements.all.direct.${stage}
-                               mv "$dbpath/requirements.build.${stage}" "$dbpath/requirements.build.direct.${stage}"
-                               mv "$dbpath/requirements.run.${stage}" "$dbpath/requirements.run.direct.${stage}"
-                       done
-                       touch "$dbpath/complete_as_node"
-                       fileedit_rm_a_line "$origin_orig" "${DBDIR}/to_be_reconf"
-                       fileedit_rm_a_line "$origin" "${DBDIR}/to_be_reconf"
-               else
-                       for level in direct full
-                       do
-                               for tag in run build
-                               do
-                                       rm -f "$dbpath/requirements.${tag}.${level}"
-                               done
-                       done
-                       for origin_tmp in "$origin" "$origin_orig"
-                       do
+                               message_echo "${DEPTH_INDEX}  ===> Already inspected merged port"
+                               fileedit_rm_a_line "$origin_orig" "${DBDIR}/to_be_reconf"
                                for inspected_level_tmp in full direct node
                                do
-                                       fileedit_rm_a_line "$origin_tmp" "${DBDIR}/ports.inspected.${inspected_level_tmp}.list"
+                                       fileedit_rm_a_line "$origin_orig" "${DBDIR}/ports.inspected.${inspected_level_tmp}.list"
                                done
-                       done
+                       fi
                fi
-               inspected_level=`database_build_get_inspected_level "$origin" "$origin_dependent"`
-               case $inspected_level in
-               full)
-                       grep -v -E -f "${DBDIR}/installed_ports.grep_pattern" \
-                               "$dbpath/requirements.all.direct.src" > ${TMPDIR}/missing.$origin_id || :
-                       inspected_levels_compatible='full direct node'
-                       ;;
-               direct)
-                       grep -v -E -f "${DBDIR}/installed_ports.grep_pattern" \
-                               "$dbpath/requirements.all.direct.src" > ${TMPDIR}/missing.$origin_id || :
-                       inspected_levels_compatible='direct node'
-                       ;;
-               node)
-                       cp /dev/null "${TMPDIR}/missing.$origin_id"
-                       inspected_levels_compatible='node'
-                       ;;
-               esac
-               nlines=`wc -l < ${TMPDIR}/missing.$origin_id`
-               iline=1
-               while [ $iline -le $nlines ]
+               # Record the completion
+               for inspected_level_tmp in $inspected_levels_compatible
                do
-                       origin_dependency=`sed -n ${iline}p "${TMPDIR}/missing.$origin_id"`
-                       iline=$(($iline+1))
-                       grep -q -E '^'`str_escape_regexp "$origin_dependency"`'$' \
-                               "${DBDIR}/ports.inspected.list" 2> /dev/null && \
-                                       continue
-                       database_build_inspect_dependencies "$origin_dependency" "$origin"
+                       fileedit_add_a_line_if_new "$origin_orig" "${DBDIR}/ports.inspected.${inspected_level_tmp}.list"
                done
-               rm -f "${TMPDIR}/missing.$origin_id"
-               dist_subdir_rpl=`database_query_get_makevar_val "$origin" DIST_SUBDIR | str_escape_replaceval_filter` || :
-               [ -n "$dist_subdir_rpl" ] && dist_subdir_rpl="$dist_subdir_rpl\/"
-               database_build_make "$origin" fetch-urlall-list \
-                       | sed -E "s/.*\/([^\/]+)$/$dist_subdir_rpl\1/" \
-                       | sort -u >> ${DBDIR}/distfiles.inspected
+               fileedit_add_a_line_if_new "$origin_orig" "${DBDIR}/ports.inspected.list"
+               fileedit_add_a_line_if_new "$origin_orig" "${DBDIR}/inspected_ports.update"
+               fileedit_rm_a_line "$origin_orig" "${DBDIR}/stage.loop_list/ports_to_inspect.remain"
+               message_echo "${DEPTH_INDEX}  ===> ok"
+               DEPTH_INDEX=${DEPTH_INDEX_orig}
        fi
-       if [ "x$origin_orig" != "x$origin" ]
+       if [ -n "$origin_dependent" -a "x$origin_orig" != "x$origin" ]
        then
-               if [ -n "$origin" ]
-               then
-                       for inspected_level_tmp in $inspected_levels_compatible
-                       do
-                               fileedit_add_a_line_if_new "$origin" "${DBDIR}/ports.inspected.${inspected_level_tmp}.list"
-                       done
-                       fileedit_add_a_line_if_new "$origin" "${DBDIR}/ports.inspected.list"
-                       fileedit_add_a_line_if_new "$origin" "${DBDIR}/inspected_ports.update"
-                       fileedit_rm_a_line "$origin" "${DBDIR}/stage.loop_list/ports_to_inspect.remain"
-               fi
+               origin_orig_regexp=`str_escape_regexp "$origin_orig"`
+               origin_replace=`str_escape_replaceval "$origin"`
+               fileedit_add_a_line_if_new "s/^$origin_orig_regexp$/$origin_replace/" "${DBDIR}/requires/$origin_dependent/rename_requirements.sed.pattern"
        fi
-       for inspected_level_tmp in $inspected_levels_compatible
-       do
-               fileedit_add_a_line_if_new "$origin_orig" "${DBDIR}/ports.inspected.${inspected_level_tmp}.list"
-       done
-       fileedit_add_a_line_if_new "$origin_orig" "${DBDIR}/ports.inspected.list"
-       fileedit_add_a_line_if_new "$origin_orig" "${DBDIR}/inspected_ports.update"
-       fileedit_rm_a_line "$origin_orig" "${DBDIR}/stage.loop_list/ports_to_inspect.remain"
-       message_echo "${DEPTH_INDEX}  ===> ok"
-
-       DEPTH_INDEX=${DEPTH_INDEX_orig}
 }
 
 # ============= Filter ignored dependencies from a list given by the standard input =============
@@ -644,10 +814,10 @@ database_build_filter_ignored_requirements ()
 {
        local origin pattern
        origin=$1
-       pattern=${DBDIR}/requires/$origin/ignored_requirements.regexp
+       pattern=${DBDIR}/requires/$origin/ignored_requirements.filter
        if [ -e "$pattern" ]
        then
-               grep -Evq -f "$pattern"
+               grep -Fxvq -f "$pattern"
        else
                cat
        fi 2> /dev/null || :
@@ -656,7 +826,7 @@ database_build_filter_ignored_requirements ()
 # ============= Build and get a list of the complete recursive dependencies of a port =============
 database_build_get_complete_recursive_dependency ()
 {
-       local tag origin suffix tmppath dbpath srcfile dstfile origin_esc num_parents loophead dstfile_tmp tmpdstpath index_loop loop_len origin_target origin_ref dbpath_target origin_ref_esc
+       local tag origin suffix tmppath dbpath srcfile dstfile num_parents loophead dstfile_tmp tmpdstpath index_loop loop_len origin_target origin_ref dbpath_target
        tag=$1
        origin=$2
        suffix=$3
@@ -671,12 +841,11 @@ database_build_get_complete_recursive_dependency ()
        fi
        if [ ! -e "$dstfile" ]
        then
-               origin_esc=`str_escape_regexp "$origin"`
                touch "$tmppath.parents"
                num_parents=`wc -l < $tmppath.parents`
-               if grep -Eq "^$origin_esc$" "$tmppath.parents"
+               if grep -Fxq "$origin" "$tmppath.parents"
                then
-                       loophead=`grep -En "^$origin_esc$" "$tmppath.parents" | tail -n 1 | cut -d : -f 1`
+                       loophead=`grep -Fxn "$origin" "$tmppath.parents" | tail -n 1 | cut -d : -f 1`
                        if [ "x$opt_force_continuation_for_looped_dependency" = xno ]
                        then
                                message_echo "ERROR: The following loop was found for requirements.${tag}${suffix}:" >&2
@@ -705,9 +874,8 @@ database_build_get_complete_recursive_dependency ()
                                        origin_target=`sed -n ${index_loop}p "$tmppath.ports_in_loop"`
                                        origin_ref=`sed -n $((${index_loop}+1))p "$tmppath.ports_in_loop"`
                                        dbpath_target=${DBDIR}/requires/$origin_target
-                                       origin_ref_esc=`str_escape_regexp "$origin_ref"`
-                                       if ! grep -Eq "^$origin_ref_esc$" "$dbpath_target/requirements.run.direct${suffix}" 2> /dev/null || \
-                                               ! grep -Eq "^$origin_ref_esc$" "$dbpath_target/requirements.build.direct${suffix}" 2> /dev/null
+                                       if ! grep -Fxq "$origin_ref" "$dbpath_target/requirements.run.direct${suffix}" 2> /dev/null || \
+                                               ! grep -Fxq "$origin_ref" "$dbpath_target/requirements.build.direct${suffix}" 2> /dev/null
                                        then
                                                message_echo 'INFO: The dependency of '$origin_target' on '$origin_ref' is ignored to terminate the loop.' >&2
                                                break
@@ -722,22 +890,25 @@ database_build_get_complete_recursive_dependency ()
                                do
                                        for tag_tmp in run build
                                        do
-                                               grep -Eq "^$origin_ref_esc$" "$dbpath_target/requirements.${tag_tmp}.direct${suffix_tmp}" 2> /dev/null && \
+                                               grep -Fxq "$origin_ref" "$dbpath_target/requirements.${tag_tmp}.direct${suffix_tmp}" 2> /dev/null && \
                                                        fileedit_add_a_line_if_new "$origin_ref" "$dbpath_target/ignored_requirements.${tag_tmp}${suffix_tmp}"
                                        done
                                        cat "$dbpath_target/ignored_requirements.run${suffix_tmp}" "$dbpath_target/ignored_requirements.build${suffix_tmp}" 2> /dev/null | sort -u > $dbpath_target/ignored_requirements.all${suffix_tmp}
                                done
-                               cat "$dbpath_target/ignored_requirements.all"* 2> /dev/null | sort -u | str_escape_regexp_filter | sed 's/^/^/;s/$/$/' > $dbpath_target/ignored_requirements.regexp
+                               cat "$dbpath_target/ignored_requirements.all"* 2> /dev/null | sort -u > $dbpath_target/ignored_requirements.filter
                        fi
                fi
                echo "$origin" >> $tmppath.parents
                tmpdstpath=${TMPDIR}/requires/$origin
                dstfile_tmp=$tmpdstpath/requirements.${tag}.full${suffix}
-               [ -d "$tmpdstpath" ] || mkdir -p "$tmpdstpath"
+               mkdir -p "$tmpdstpath"
                database_build_filter_ignored_requirements "$origin" < $srcfile | while read origin_requirement
                do
-                       database_build_get_complete_recursive_dependency "$tag" "$origin_requirement" "$suffix" > $tmppath.recursive_dependency
-                       [ -e "$dbpath/ignored_requirements.regexp" ] && echo "$origin_requirement" | grep -Eq -f "$dbpath/ignored_requirements.regexp" && continue
+                       database_build_get_complete_recursive_dependency "$tag" "$origin_requirement" "$suffix" \
+                               > $tmppath.recursive_dependency
+                       [ -e "$dbpath/ignored_requirements.filter" ] && \
+                               echo "$origin_requirement" | grep -Fxq -f "$dbpath/ignored_requirements.filter" 2> /dev/null && \
+                               continue
                        echo "$origin_requirement"
                        cat "$tmppath.recursive_dependency"
                done > $dstfile_tmp
@@ -861,100 +1032,9 @@ eof
 database_build_order_ports_considering_dependencies ()
 {
        touch "${DBDIR}/reinst_order.list.tmp"
-       cat > ${TMPDIR}/order_dependencies.awk << eof
-BEGIN {
-       it = 0;
-       i = 0;
-}
-{
-       if (NF == 0)
-       {
-               i = 0;
-       }
-       else
-       {
-               if (i == 0)
-               {
-                       target = \$0;
-                       sub (/\/requirements.all\.full$/, "", target);
-                       sub (/^\.\//, "", target);
-                       srcikey[it] = target;
-                       srckeyi[target] = it;
-                       it++;
-               }
-               else
-               {
-                       src[it-1,i-1] = \$0;
-                       srcimax[it-1] = srcsize[it-1] = i;
-               }
-               i++;
-       }
-}
-END {
-       ntargets = it;
-       norder = 0;
-       order_str = "";
-       icycle = 0;
-       lf_order_str = "";
-       while (1)
-       {
-               is_operated = 0;
-               for (it = 0; it < ntargets; it++)
-               {
-                       if (!(it in srcikey)) continue;
-                       if (srcsize[it] > 0) continue;
-                       is_operated = 1;
-                       target = srcikey[it];
-                       delete srcikey[it];
-                       order[norder++] = target;
-                       order_str = order_str lf_order_str;
-                       order_str = sprintf ("%s%s", order_str, target);
-                       lf_order_str = "\n";
-                       for (jt = 0; jt < ntargets; jt++)
-                       {
-                               for (j = 0; j < srcimax[jt]; j++)
-                               {
-                                       if ((jt,j) in src && src[jt,j] == target)
-                                       {
-                                               delete src[jt,j];
-                                               srcsize[jt]--;
-                                               break;
-                                       }
-                               }
-                       }
-               }
-               if (is_operated == 0) break;
-               icycle++;
-       }
-       reinst_order_list = sprintf ("%s%s", ENVIRON["DBDIR"], "/reinst_order.list.tmp");
-       print order_str > reinst_order_list;
-       unsatisfied = "";
-       for (it = 0; it < ntargets; it++)
-       {
-               if (srcsize[it] == 0) continue;
-               reqs = "";
-               sp_reqs = "";
-               for (i = 0; i < srcimax[it]; i++)
-               {
-                       if ((it,i) in src)
-                       {
-                               reqs = reqs sp_reqs src[it,i];
-                               sp_reqs = ", ";
-                       }
-               }
-               unsatisfied = sprintf ("%s%s [%d] (%s)\n", unsatisfied, srcikey[it], srcsize[it], reqs);
-       }
-       if (unsatisfied != "")
-       {
-               unsatisfied_list = sprintf ("%s%s", ENVIRON["DBDIR"], "/unsatisfied.list");
-               print unsatisfied > unsatisfied_list;
-               exit 1;
-       }
-}
-eof
        (cd "${DBDIR}/requires" && \
                find . -depth 3 -name requirements.all.full -exec echo {} \; -exec cat {} \; -exec echo \;) | \
-               env "DBDIR=${DBDIR}" awk -f "${TMPDIR}"/order_dependencies.awk || return
+               env "DBDIR=${DBDIR}" awk -f "${LIBEXECDIR}"/order_dependencies.awk || return
        grep -v '^$' "${DBDIR}/reinst_order.list.tmp" > "${DBDIR}/reinst_order.list" || :
 }
 
@@ -990,7 +1070,7 @@ _database_build_reset_a_port_confdb ()
        cat "${DBDIR}/replace/$origin/origin" 2> /dev/null || :
 }
 
-# ============= Clear database directories for an origin =============
+# ============= Clear database directories for a flavored origin =============
 database_build_clear_db_dirs ()
 {
        local origin db
@@ -1012,7 +1092,7 @@ database_build_forget ()
        database_build_clear_db_dirs "$origin"
 }
 
-# ============= Patch to the temporary database so as to re-inspect and reinstall ports whose configurations were changed =============
+# ============= Overlay onto the temporary database so as to re-inspect and reinstall ports whose configurations were changed =============
 database_build_patch_reconf ()
 {
        local origin origin_replace
@@ -1021,6 +1101,7 @@ database_build_patch_reconf ()
        [ -d "${DBDIR}/initial/$origin" -o -d "${DBDIR}/requires/$origin" ] && \
                fileedit_add_a_line_if_new "$origin" "${DBDIR}/stage.loop_list/ports_to_inspect"
        fileedit_add_a_line_if_new "$origin" "${DBDIR}/to_be_reconf"
+       fileedit_rm_a_line "$origin" "${DBDIR}/done_required_ports_to_inspect"
        [ -z "$origin_replace" ] || database_build_patch_reconf "$origin_replace"
        database_build_clear_db_dirs "$origin"
 }
@@ -1028,23 +1109,19 @@ database_build_patch_reconf ()
 # ============= Post-processes after finishing to inspect dependencies =============
 database_build_post_inspect_dependencies ()
 {
-       local table
+       local table tmpfile
+       tmpfile=${TMPDIR}/database_build_post_inspect_dependencies
        touch "${DBDIR}/obsolete_ports" "${DBDIR}/inspected_ports.update"
        find "${DBDIR}/requires" -depth 2 -type d \
                | sed -E 's|.*/([^/]+/[^/]+)$|\1|' > ${DBDIR}/inspected_ports
        find "${DBDIR}/initial" -depth 2 -type d \
                | sed -E 's|.*/([^/]+/[^/]+)$|\1|' > ${DBDIR}/inspected_ports.initial
        sort -u "${DBDIR}/inspected_ports" "${DBDIR}/inspected_ports.initial" > ${DBDIR}/inspected_ports.all
-       str_escape_regexp_filter < ${DBDIR}/inspected_ports \
-               | sed 's/^/^/; s/$/$/' > ${DBDIR}/inspected_ports.grep_pattern
-       str_escape_regexp_filter < ${DBDIR}/inspected_ports.initial \
-               | sed 's/^/^/; s/$/$/' > ${DBDIR}/inspected_ports.initial.grep_pattern
-       str_escape_regexp_filter < ${DBDIR}/inspected_ports.all \
-               | sed 's/^/^/; s/$/$/' > ${DBDIR}/inspected_ports.all.grep_pattern
-       cat "${DBDIR}/conf/HOLD_PORTS.grep_pattern" "${DBDIR}/need.grep_pattern" \
-               2> /dev/null > ${TMPDIR}/INSPECT_ALL_DEPENDENCIES:obsolete_ports.exclude.grep_pattern || :
-       grep -v -E -f "${TMPDIR}/INSPECT_ALL_DEPENDENCIES:obsolete_ports.exclude.grep_pattern" \
-               "${DBDIR}/obsolete_ports" > ${DBDIR}/obsolete_ports.can_be_deleted || :
+       {
+               cat "${DBDIR}/conf/HOLD:PORTS.parsed" || :
+               cat "${DBDIR}/need.list" || :
+       } 2> /dev/null | sort -u > $tmpfile.obsolete_ports.exclude
+       grep -v -Fx -f "$tmpfile.obsolete_ports.exclude" "${DBDIR}/obsolete_ports" > ${DBDIR}/obsolete_ports.can_be_deleted || :
        cp /dev/null "${DBDIR}/REPLACE.complete_sed_pattern.tmp"
        cp /dev/null "${DBDIR}/REVERSE_REPLACE.complete_sed_pattern.tmp"
        find "${DBDIR}/replace" -depth 3 -type f -name origin | while read nodepath
@@ -1063,8 +1140,8 @@ database_build_post_inspect_dependencies ()
        mv "${DBDIR}/REVERSE_REPLACE.complete_sed_pattern.tmp" "${DBDIR}/REVERSE_REPLACE.complete_sed_pattern"
        if [ `cat "${DBDIR}/inspected_ports.update" 2> /dev/null | wc -l` -gt 0 ]
        then
-               grep -E -f "${DBDIR}/inspected_ports.all.grep_pattern" "${DBDIR}/inspected_ports.update" \
-                       > ${DBDIR}/inspected_ports.update.tmp || :
+               grep -Fx -f "${DBDIR}/inspected_ports.all" "${DBDIR}/inspected_ports.update" \
+                       > ${DBDIR}/inspected_ports.update.tmp 2> /dev/null || :
                mv "${DBDIR}/inspected_ports.update.tmp" "${DBDIR}/inspected_ports.update"
                if [ $opt_only_target_scope = yes ]
                then
@@ -1096,6 +1173,6 @@ database_build_post_inspect_dependencies ()
                sed -E -f "${DBDIR}/REPLACE.complete_sed_pattern" \
                        "${DBDIR}/stage.loop_list/target_$table.specified" \
                        > ${DBDIR}/stage.loop_list/target_$table.replaced.specified
-       done    
+       done
        cp /dev/null "${DBDIR}/update_dependencies"
 }
diff --git a/lib/libdatabase_maintain.sh b/lib/libdatabase_maintain.sh
new file mode 100644 (file)
index 0000000..05fa2ee
--- /dev/null
@@ -0,0 +1,197 @@
+#!/bin/sh -e
+# ==============================================================================
+# portsreinstall library script
+# - Operations for maintaining the temporary database -
+# Copyright (C) 2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# This software is distributed under the 2-Clause BSD License.
+# ==============================================================================
+
+
+# ============= Variables =============
+DATABASE_VERSION=
+DATABASE_IS_OBSOLETE=no
+
+
+# ============= Cleaning of the temporary database =============
+database_maintain_clean_all ()
+{
+       rm -rf "${DBDIR}"
+}
+
+# ============= Load a temporary database from an archive =============
+database_maintain_load ()
+{
+       local filepath dbdir_parent
+       filepath=$1
+       dbdir_parent=`dirname "${DBDIR}"`
+       mkdir -p "$dbdir_parent"
+       tar xzf "$filepath" -C "$dbdir_parent" --exclude "*/.lock"
+}
+
+# ============= Save the temporary database to an archive =============
+database_maintain_save ()
+{
+       local filepath dbdir_parent dbdir_node
+       filepath=$1
+       dbdir_parent=`dirname "${DBDIR}"`
+       dbdir_node=`basename "${DBDIR}"`
+       tar czf "$filepath" -C "$dbdir_parent" "$dbdir_node"
+}
+
+# ============= Creation of the temporary database =============
+database_maintain_create ()
+{
+       local subdir
+       [ `id -u` -eq 0 ] && mkdir -p "${DBDIR}"
+       misc_lock_duplicated_executions "${DBDIR}/.lock"
+       if [ -e "${DBDIR}/MYVERSION" ]
+       then
+               if ! grep -q -E "$COMPATIBLE_VERSIONS" "${DBDIR}/MYVERSION" 2> /dev/null
+               then
+                       message_echo "ERROR: The current temporary database is incompatible. You must delete it by" >&2
+                       message_echo "        ${APPNAME} clean force" >&2
+                       message_echo "       in order to enable the current version." >&2
+                       exit 1
+               fi
+       elif misc_is_superuser_privilege
+       then
+               echo "$MYVERSION" > ${DBDIR}/MYVERSION
+       fi
+       DATABASE_VERSION=`cat "${DBDIR}"/MYVERSION 2> /dev/null || :`
+       misc_is_superuser_privilege || return 0
+       for subdir in initial requires replace targets obsolete backup_packages \
+               stage.loop_list stage.complete stage.reinit_loop stage.depends
+       do
+               mkdir -p "${DBDIR}/$subdir"
+       done
+}
+
+# ============= Mark the use of the temporary database =============
+database_maintain_mark_use ()
+{
+        touch "${DBDIR}/in_use"
+}
+
+# ============= Check the use of the temporary database =============
+database_maintain_chk_use ()
+{
+        [ -e "${DBDIR}/in_use" ]
+}
+
+# ============= Refresh the temporary database =============
+database_maintain_refresh ()
+{
+       misc_is_superuser_privilege || return
+       [ $opt_suppress_obsolete_db_clean = no ] || return
+       message_echo "INFO: The temporary database is cleaned up."
+       message_echo
+       [ -d "${DBDIR}" -a ! -d "${DBDIR}.tmp" ] && mv "${DBDIR}" "${DBDIR}.tmp"
+       database_maintain_create
+       mv "${DBDIR}.tmp/saved_options.sh" "${DBDIR}" 2> /dev/null || :
+       mv "${DBDIR}.tmp/backup_packages" "${DBDIR}" 2> /dev/null || :
+       mv "${DBDIR}.tmp/backup_pkgarcs.lst" "${DBDIR}" 2> /dev/null || :
+       rm -rf "${DBDIR}.tmp"
+}
+
+# ============= Clean up the temporary database for upgrade of this utility =============
+database_maintain_clean_for_self_upgrade ()
+{
+       misc_is_superuser_privilege || return
+       [ $opt_suppress_obsolete_db_clean = no ] || return
+       rm -rf "${DBDIR}"
+       database_maintain_create
+       [ -e "${DBDIR}/MYVERSION" ] && mv "${DBDIR}/MYVERSION" "${DBDIR}/MYVERSION.prev"
+       :
+}
+
+# ============= Check whether the temporary database is newer than the ports tree and refresh if so =============
+database_maintain_refresh_if_obsolete ()
+{
+       if [ "${PORTS_INDEX_DB}" -nt "${DBDIR}"/MYVERSION ] && misc_is_superuser_privilege
+       then
+               if [ $opt_suppress_obsolete_db_clean = no -a "z${command}" = zclean ]
+               then
+                       DATABASE_IS_OBSOLETE=no
+                       message_echo "WARNING: The temporary database is older than the ports tree." >&2
+                       database_maintain_refresh || DATABASE_IS_OBSOLETE=yes
+               else
+                       DATABASE_IS_OBSOLETE=yes
+               fi
+       else
+               DATABASE_IS_OBSOLETE=no
+       fi
+}
+
+# ============= Resetting of the temporary database =============
+database_maintain_reset ()
+{
+       local mode
+       mode=$1
+       if [ $mode = keepstatus ]
+       then
+               if [ ! -d "${DBDIR}/prevset" ]
+               then
+                       mkdir -p "${DBDIR}/prevset"
+                       {
+                               echo requires
+                               echo notes
+                               echo to_be_reconf
+                               echo failed.list
+                               echo damaged_package
+                               echo manually_done.list
+                               for tag in all run build none
+                               do
+                                       for level in full direct
+                                       do
+                                               echo "success.$tag.$level.list"
+                                       done
+                               done
+                       } | while read content
+                       do
+                               [ -e "${DBDIR}/$content" ] && mv "${DBDIR}/$content" "${DBDIR}/prevset"
+                       done
+               fi
+       else
+               rm -rf "${DBDIR}"/requires.prev "${DBDIR}"/notes.prev
+       fi
+       find "${DBDIR}" -depth 1 \
+               -not \( -name saved_options.sh \
+                       -or -name MYVERSION -or -name .lock \
+                       -or -name journal -or -name prevset \
+                       -or -name backup_failure -or -name installed_ports \) \
+               -exec rm -rf {} \; 2> /dev/null || :
+       touch "${DBDIR}/MYVERSION"
+       case $mode in
+       all )
+               command_exec_without_pkgtools__notify_reset_options
+               rm -f "${DBDIR}/saved_options.sh" "${DBDIR}/prevset" "${DBDIR}/journal"*
+               ;;
+       keepopts | keepstatus )
+               (
+                       opt_batch_mode=yes
+                       while read srcline
+                       do
+                               command_flexconf_update_taboo $srcline
+                       done < ${DBDIR}/journal/taboo || :
+                       while read srcline
+                       do
+                               command_flexconf_update_freeze $srcline
+                       done < ${DBDIR}/journal/freeze || :
+                       while read srcline
+                       do
+                               command_flexconf_update_need $srcline
+                       done < ${DBDIR}/journal/need || :
+                       while read srcline
+                       do
+                               command_flexconf_update_noneed $srcline
+                       done < ${DBDIR}/journal/noneed || :
+               ) 2> /dev/null
+               ;;
+       esac
+}
+
+# ============= Clear the data of previous progress status =============
+database_maintain_clear_prevset ()
+{
+       rm -rf "${DBDIR}/prevset"
+}
index de7e8b5..1d63468 100644 (file)
@@ -2,7 +2,7 @@
 # ==============================================================================
 # portsreinstall library script
 # - Operations for queries to the temporary database -
-# Copyright (C) 2013-2017 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# Copyright (C) 2013-2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
 # This software is distributed under the 2-Clause BSD License.
 # ==============================================================================
 
@@ -16,11 +16,10 @@ database_query_show_list_failure ()
                message_echo "INFO: No item is registered in this list."
                return 1
        fi
-       grep -v -E -f "${DBDIR}/ports_to_delete.grep_pattern" "${DBDIR}/failed.list" \
+       grep -v -E -f "${DBDIR}/ports_to_delete.grep_pattern" "${DBDIR}/failed.list" 2> /dev/null \
                | while read origin
        do
-               origin_regexp=`str_escape_regexp "$origin"`
-               grep -q -E "^$origin_regexp$" "${DBDIR}/stage.loop_list/ports_to_delete" 2> /dev/null \
+               grep -q -Fx "$origin" "${DBDIR}/stage.loop_list/ports_to_delete" 2> /dev/null \
                        || echo "$origin"
        done > $tmp_valid
        if [ `cat "$tmp_valid" 2> /dev/null | wc -l` -eq 0 ]
@@ -32,15 +31,13 @@ database_query_show_list_failure ()
        do
                note=`cat "${DBDIR}/notes/$origin/note_failtre" 2> /dev/null || :`
                resolved=no
-               grep -q -E "^`str_escape_regexp \"$origin\"`$" \
-                       "${DBDIR}/manually_done.list" 2> /dev/null \
-                       && resolved=yes
-               pkgtag=`cat "${DBDIR}/requires/$origin/pkgtag" 2> /dev/null || :`
+               grep -q -Fx "$origin" "${DBDIR}/manually_done.list" 2> /dev/null && resolved=yes
+               pkgtag=`cat "${DBDIR}/moved_from/$origin/pkgtag" 2> /dev/null || :`
                if [ $opt_batch_mode = no ]
                then
                        case $resolved in
-                       no    resolved=;;
-                       yes   resolved=', resolved';;
+                       no )    resolved=;;
+                       yes )   resolved=', resolved';;
                        esac
                        if [ -n "$note" ]
                        then
@@ -61,7 +58,7 @@ database_query_show_list_failure ()
        :
 }
 
-# ============= Show a list of failed restoration of conflicts =============
+# ============= Show a list of failed restoration of conflict =============
 database_query_show_list_failed_conflicts_restoration ()
 {
        if [ `cat "${DBDIR}/deleted_conflicts" 2> /dev/null | wc -l` -eq 0 ]
@@ -73,7 +70,7 @@ database_query_show_list_failed_conflicts_restoration ()
                | while read origin pkg
                do
                        pkg_regexp=`str_escape_regexp "$pkg"`
-                       against=`grep -E "^$pkg_regexp:" "${DBDIR}/forbidden_conflicts" 2> /dev/null | cut -d : -f 2 | sort -u`
+                       against=`grep -E "^$pkg_regexp:" "${DBDIR}/forbidden_conflicts" 2> /dev/null | cut -d : -f 2,3 | sort -u`
                        if [ $opt_batch_mode = no ]
                        then
                                if [ -n "$pkg" ]
@@ -85,28 +82,28 @@ database_query_show_list_failed_conflicts_restoration ()
                                if [ -n "$against" ]
                                then
                                        echo -n " against "
-                                       against=`echo "$against" | tr '\n' ' '`
+                                       against=`echo "$against" | sed 's/:/(/;s/$/)/' | tr '\n' ' '`
                                        str_linearize_list_and "$against"
                                else
                                        echo
                                fi
                        else
-                               against=`echo "$against" | tr '\n' , | sed 's/,$//'`
+                               against=`echo "$against" | tr '\n' '|' | sed 's/,$//'`
                                printf '%s\t%s\t%s\n' "$origin" "$pkg" "$against"
                        fi
                done
        :
 }
 
-# ============= Insert initial origins to a list of origins =============
+# ============= Insert initial flavored origins to a list of flavored origins =============
 database_query_add_initial_origins ()
 {
        local origin
        while read origin
        do
                echo "$origin"
-               [ -e "${DBDIR}/requires/$origin/initial_orig" ] || continue
-               cat "${DBDIR}/requires/$origin/initial_orig"
+               [ -e "${DBDIR}/moved_from/$origin/initial_orig" ] || continue
+               cat "${DBDIR}/moved_from/$origin/initial_orig"
        done
        :
 }
@@ -152,20 +149,17 @@ database_query_get_target_attributes ()
 # ============= Check whether (re/de)installation of a port is suppressed =============
 database_query_is_a_port_suppressed ()
 {
-       local origin flag
+       local origin flags flag
        origin=$1
-       if [ $opt_suppress_self_upadte = yes ]
-       then
-               flag=SUPPRESSED_SELF
-       elif [ $opt_suppress_pkgtools_upadte = yes ]
-       then
-               flag=SUPPRESSED_PKGNG
-       else
-               return 1
-       fi
-       for db in initial requires
+       flags=
+       [ $opt_suppress_self_upadte = yes ] && flags=SUPPRESSED_SELF
+       [ $opt_suppress_pkgtools_upadte = yes ] && flags="$flags SUPPRESSED_PKGNG"
+       for flag in $flags
        do
-               [ -e "${DBDIR}/$db/$origin/$flag" ] && return
+               for db in initial moved_from
+               do
+                       [ -e "${DBDIR}/$db/$origin/$flag" ] && return
+               done
        done
        return 1
 }
@@ -173,13 +167,14 @@ database_query_is_a_port_suppressed ()
 # ============= Check whether a port needs to be updated or upgraded =============
 database_query_does_a_port_need_update ()
 {
-       local origin dbpath new_version current_version
+       local origin dbpath frompath new_version current_version
        origin=$1
        dbpath=${DBDIR}/requires/$origin
+       frompath=${DBDIR}/moved_from/$origin
        [ -e "$dbpath/conf_updated" ] && return
        [ -e "$dbpath/new_version" ] || return
        new_version=`cat "$dbpath/new_version"`
-       current_version=`cat "$dbpath/current_version"`
+       current_version=`cat "$frompath/current_version"`
        [ "x$current_version" != "x$new_version" ]
 }
 
@@ -217,7 +212,7 @@ database_query_get_makevar_val ()
 # ============= Check whether configurations for a port is default =============
 database_query_is_default_conf ()
 {
-       local origin mode dbpath tmp_msg is_customized is_requiremnt_replaced files origin_regexp tmp_old tmp_new origin_requirement tmp_msg_customized
+       local origin mode dbpath tmp_msg is_customized is_requiremnt_replaced files tmp_old tmp_new origin_requirement tmp_msg_customized
        origin=$1
        mode=$2
        dbpath=${DBDIR}/requires/$origin
@@ -232,13 +227,12 @@ database_query_is_default_conf ()
                        echo "Knobs and miscellaneous customization by $files," >> $tmp_msg
                        is_customized=yes
                fi
-               if ! diff "$dbpath/ports_options.default" "$dbpath/ports_options.current" > /dev/null 2>&1
+               if ! diff -q "$dbpath/ports_options.default" "$dbpath/ports_options.current" > /dev/null 2>&1
                then
                        echo "Non-default port options," >> $tmp_msg
                        is_customized=yes
                fi
-               origin_regexp=`str_escape_regexp "$origin"`
-               if grep -q -E "^$origin_regexp$" "${DBDIR}/conf/NOPKG:PORTS.parsed" 2> /dev/null
+               if grep -q -Fx "$origin" "${DBDIR}/conf/NOPKG:PORTS.parsed" 2> /dev/null
                then
                        echo "Explicit specification as non-default in ${APPNAME}.conf," >> $tmp_msg
                        is_customized=yes
@@ -279,7 +273,7 @@ database_query_is_default_conf ()
 }
 
 # ============= Output of lists in which each matching port is registered =============
-database_query_for_list_inclusion_of_matching_port ()
+database_query_show_list_inclusion_of_matching_port ()
 {
        local grandtitle lists pkgnamedb deptag level isfirst origin_target pkg_target table_target
        grandtitle=$1
@@ -325,18 +319,16 @@ database_query_for_list_inclusion_of_matching_port ()
        :
 }
 
-
-# ============= Output of "show" command for each matching port =============
-database_query_for_each_matching_port ()
+# ============= Output of "show" command for port lists =============
+database_query_show_port_lists ()
 {
-       local grandtitle title list pkgnamedb deptag level isfirst origin_target pkg_target table_target list_target
+       local grandtitle title list listdb pkgnamedb isfirst origin_target pkg_target table_target list_target
        grandtitle=$1
        title=$2
        list=$3
-       pkgnamedb=$4
-       deptag=$5
-       level=$6
-       shift 6
+       listdb=$4
+       pkgnamedb=$5
+       shift 5
        message_echo "[$grandtitle]"
        message_dependency_scope
        message_echo
@@ -354,7 +346,7 @@ database_query_for_each_matching_port ()
                isfirst=n
                [ $opt_batch_mode = no ] && printf "$title\n" "$origin_target ($pkg_target)"
                list_target=
-               for table_target in $pkgnamedb
+               for table_target in $listdb
                do
                        list_target=${DBDIR}/$table_target/$origin_target/$list
                        [ -e "$list_target" ] && break
@@ -395,6 +387,53 @@ database_query_for_each_matching_port ()
        :
 }
 
+# ============= Output of "show" command for two column lists =============
+database_query_show_two_column_lists ()
+{
+       local grandtitle title list listdb pkgnamedb isfirst origin_target pkg_target table_target list_target
+       grandtitle=$1
+       title=$2
+       list=$3
+       listdb=$4
+       pkgnamedb=$5
+       shift 5
+       message_echo "[$grandtitle]"
+       message_echo
+       isfirst=y
+       for origin_target in `pkgsys_eval_ports_glob "$@"`
+       do
+               pkg_target=
+               for table_target in $pkgnamedb
+               do
+                       pkg_target=`cat "${DBDIR}/$table_target/$origin_target/pkgtag" 2> /dev/null` || :
+                       [ -n "$pkg_target" ] && break
+               done
+               [ -n "$pkg_target" ] || continue
+               [ "$isfirst" = y ] || message_echo
+               isfirst=n
+               [ $opt_batch_mode = no ] && printf "$title\n" "$origin_target ($pkg_target)"
+               list_target=
+               for table_target in $listdb
+               do
+                       list_target=${DBDIR}/$table_target/$origin_target/$list
+                       [ -e "$list_target" ] && break
+               done
+               [ -e "$list_target" ] || continue
+               if [ $opt_batch_mode = no ]
+               then
+                       sed 's/[[:space:]]/: /' < $list_target
+               else
+                       cat  < $list_target
+               fi
+       done
+       if [ "$isfirst" = y ]
+       then
+               message_echo "ERROR: No inspected port matches the glob(s)." >&2
+               exit 1
+       fi
+       :
+}
+
 # ============= Output of "show" command for a single list =============
 database_query_show_single_list ()
 {
@@ -409,17 +448,23 @@ database_query_show_single_list ()
                message_echo "INFO: No item is registered in this list."
                return 1
        fi
+       if ! program_chk_stage_complete PREPARATION
+       then
+               message_echo "WARNING: The temporary database is incomplete. The raw list is shown." >&2
+               cat "${DBDIR}/$list"
+               return
+       fi
        rm -f "$tmpflag_exists"
        put_blankline=
        if [ -n "$flag_filter_only_target" \
                -a -n "$opt_target_itself$opt_target_dependents$opt_target_requirements" ]
        then
-               message_echo "INFO: Ports outside of the target scope are excluded."
+               message_echo "WARNING: Ports outside of the target scope are excluded." >&2
                put_blankline=y
        fi
        if [ -n "$flag_filter_skip_unchanged" -a $opt_skip_unchanged = yes ]
        then
-               message_echo "INFO: Ports which have been the newest with their all requirements from the first are excluded."
+               message_echo "WARNING: Ports which have been the newest with their all requirements from the first are excluded." >&2
                put_blankline=y
        fi
        [ -n "$put_blankline" ] && message_echo
@@ -483,7 +528,7 @@ database_query_show_single_list_exec ()
        flag_filter_only_target=
        pkgnamedb='requires obsolete initial'
        case $subject in
-       todo)
+       todo )
                message_echo "The following ports remain in the (re)installation queue for the current do/redo process:"
                message_echo "It is noted that ports to be skipped can be included here."
                message_dependency_scope
@@ -493,7 +538,7 @@ database_query_show_single_list_exec ()
                flag_filter_skip_unchanged=necessary_upgrade.$dbsuffix
                flag_filter_only_target=y
                ;;
-       done)
+       done )
                message_echo "The following ports have been successfully (re)installed or newly installed:"
                message_dependency_scope
                message_echo
@@ -501,7 +546,7 @@ database_query_show_single_list_exec ()
                flag_filter_skip_unchanged=necessary_upgrade_completed.$dbsuffix
                flag_filter_only_target=y
                ;;
-       redo)
+       redo )
                message_echo "The following ports need (re)installation but are to be skipped until any of their failed requirements succeeds:"
                message_dependency_scope
                message_echo
@@ -509,46 +554,51 @@ database_query_show_single_list_exec ()
                flag_filter_skip_unchanged=necessary_upgrade.$dbsuffix
                flag_filter_only_target=y
                ;;
-       resolved)
+       resolved )
                message_echo "The following ports had problems which have been manually resolved:"
                message_echo
                list=manually_done.list
                ;;
-       failure)
+       failure )
                message_echo "The following ports experienced failures and kept to be old or uninstalled:"
                message_echo
                database_query_show_list_failure
                return
                ;;
-       conflict)
-               message_echo "The following ports are temporarily deleted due to conflicts:"
+       conflict )
+               message_echo "The following ports are temporarily deleted due to conflict:"
                message_echo
                database_query_show_list_failed_conflicts_restoration
                return
                ;;
-       taboo)
+       taboo )
                message_echo "The following ports are registered as taboo:"
                message_echo
                list=taboo.all.list
                ;;
-       need)
+       freeze )
+               message_echo "The following ports are registered to freeze:"
+               message_echo
+               list=freeze.all.list
+               ;;
+       need )
                message_echo "The following ports are registered as necessary:"
                message_echo
                list=need.list
                ;;
-       noneed)
+       noneed )
                message_echo "The following ports are registered as unnecessary:"
                message_echo
                list=noneed.list
                ;;
-       restored)
+       restored )
                message_echo "The following leaf, obsolete or unneeded ports had been once deleted but are to be or have been restored:"
                message_echo
                list=stage.loop_list/ports_to_restore
                pkgnamedb='obsolete initial'
                flag_filter_only_target=y
                ;;
-       deleted)
+       deleted )
                message_echo "The following leaf, obsolete or unneeded ports are to be or have been deleted:"
                message_echo
                list=stage.loop_list/ports_to_delete
@@ -563,7 +613,7 @@ database_query_show_single_list_exec ()
 # ============= Check whether a port is registered in a list =============
 database_query_exists_in_list ()
 {
-       local origin subject deptag level tmp_list dbsuffix origin_esc origin_ptn
+       local origin subject deptag level tmp_list dbsuffix origin_esc
        origin=$1
        subject=$2
        deptag=$3
@@ -571,44 +621,87 @@ database_query_exists_in_list ()
        tmp_list=${TMPDIR}/database_query_exists_in_list:list
        dbsuffix=$deptag.$level
        origin_esc=`str_escape_regexp "$origin"`
-       origin_ptn="^$origin_esc$"
        case $subject in
-       todo)
+       todo )
                list=stage.loop_list/reinst_todo.remain
                [ ${DBDIR}/reinst_order.list -nt ${DBDIR}/$list ] && list=reinst_order.list
                ;;
-       done)
+       done )
                list=success.$dbsuffix.list
                ;;
-       redo)
+       redo )
                list=todo_after_requirements_succeed.$dbsuffix.list
                ;;
-       resolved)
+       resolved )
                list=manually_done.list
                ;;
-       failure)
+       failure )
                list=failed.list
                ;;
-       conflict)
+       conflict )
                grep -v -E -f "${DBDIR}/ports_to_delete.grep_pattern_col1" "${DBDIR}/deleted_conflicts" 2> /dev/null \
                        | grep -q -E "^${origin_esc}[[:space:]]"
                return
                ;;
-       taboo)
+       taboo )
                list=taboo.all.list
                ;;
-       need)
+       freeze )
+               list=freeze.all.list
+               ;;
+       need )
                list=need.list
                ;;
-       noneed)
+       noneed )
                list=noneed.list
                ;;
-       restored)
+       restored )
                list=stage.loop_list/ports_to_restore
                ;;
-       deleted)
+       deleted )
                list=stage.loop_list/ports_to_delete
                ;;
        esac
-       grep -q -E "$origin_ptn" "${DBDIR}/$list" 2> /dev/null
+       grep -q -Fx "$origin" "${DBDIR}/$list" 2> /dev/null
+}
+
+# ============= Check whether the requirements of installed packages match the port configuration =============
+database_query_dependency_matching ()
+{
+       local origin pkg tmp_inst tmp_db
+       origin=$1
+       [ -d "${DBDIR}/requires/$origin" ] || return
+       tmp_inst=${TMPDIR}/database_query_dependency_matching.installed
+       tmp_db=${TMPDIR}/database_query_dependency_matching.configured
+       pkg=`database_build_get_new_pkgname "$origin"`
+       [ -n "$pkg" ] || return
+       pkg_info_e "$pkg" || return
+       pkg_info_qr "$pkg" | grep -v '^[[:space:]]*$' | sort -u > $tmp_inst
+       database_build_get_full_run_requirement_pkgs "$origin" > $tmp_db
+       diff "$tmp_inst" "$tmp_db" > /dev/null 2>/dev/null
+}
+
+# ============= Check whether any of the requirements are locked because being missing ports to freeze =============
+database_query_are_requirements_not_locked ()
+{
+       local origin
+       origin=$1
+       cat "${DBDIR}/requires/$origin/requirements.all.direct" 2> /dev/null | while read origin_requirement
+       do
+               pkg_requirement=`pkgsys_get_installed_pkg_from_origin "$origin_requirement"` || :
+               if grep -q -Fx "$origin_requirement" "${DBDIR}/freeze.all.list" 2> /dev/null
+               then
+                       [ -n "$pkg_requirement" ] || return
+               elif [ -z "$pkg_requirement" ]
+               then
+                       database_query_are_requirements_not_locked "$origin_requirement" || return
+               fi
+       done
+       :
+}
+
+# ============= Check whether any of progress is made in the current run =============
+database_query_is_any_progress ()
+{
+       [ `cat "${DBDIR}/new_success_in_current_run" 2> /dev/null | wc -l` -gt 0 ]
 }
index 057f495..6364b66 100644 (file)
@@ -2,20 +2,17 @@
 # ==============================================================================
 # portsreinstall library script
 # - Operations for recording operation results to the temporary database -
-# Copyright (C) 2013-2017 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# Copyright (C) 2013-2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
 # This software is distributed under the 2-Clause BSD License.
 # ==============================================================================
 
 # ============= Update records by reflecting a successful result of (re/de)installation of a port =============
 database_record_success ()
 {
-       local origin nodedir tmp_grep_failed dbdir_esc tag level dbsuffix
+       local origin nodedir dbdir_esc tag level dbsuffix
        origin=$1
        nodedir=${DBDIR}/requires/$origin
-       tmp_grep_failed=${TMPDIR}/database_record_success:grep_failed.list
        fileedit_add_a_line_if_new "$origin" "${DBDIR}/new_success_in_current_run"
-       cat "${DBDIR}/failed.list" 2> /dev/null | str_escape_regexp_filter \
-               | sed "s|^|^|; s|$|$|" > $tmp_grep_failed || :
        dbdir_esc=`str_escape_replaceval "${DBDIR}/requires/"`
        for tag in all run build none
        do
@@ -36,7 +33,7 @@ database_record_success ()
                                {
                                        cat "$nodedir/requirements.$dbsuffix" 2> /dev/null
                                        [ $level = full ] && cat "$nodedir/ignored_requirements.$tag" 2> /dev/null
-                               } | grep -q -E -f "$tmp_grep_failed"
+                               } | grep -q -Fx -f "${DBDIR}/failed.list" 2> /dev/null
                        then
                                fileedit_rm_a_line "$origin" "${DBDIR}/success.$dbsuffix.list"
                                fileedit_add_a_line_if_new "$origin" "${DBDIR}/todo_after_requirements_succeed.$dbsuffix.list"
index 402fb38..b87a298 100644 (file)
@@ -2,56 +2,50 @@
 # ==============================================================================
 # portsreinstall library script
 # - Deinstallation processes -
-# Copyright (C) 2013-2017 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# Copyright (C) 2013-2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
 # This software is distributed under the 2-Clause BSD License.
 # ==============================================================================
 
 # ============= Dialog for selection of removing new leaf ports =============
 deinstall_select_leaf_ports_to_delete_dialog ()
 {
-       local src dst_selected dst_unselected grepptn itemlist title desc
+       local src dst_selected dst_unselected itemlist title desc
        src=$1
        dst_selected=$2
        dst_unselected=$3
-       grepptn=${TMPDIR}/deinstall_select_leaf_ports_to_delete_dialog::grep
        itemlist=${TMPDIR}/deinstall_select_leaf_ports_to_delete_dialog::itemlist
        title='New leaf ports and their exclusive requirements to be deleted'
        desc='Unchecked ones are preserved with their requirements.\nCancellation means to preserve all.'
        while read origin
        do
-               pkgtag=`cat "${DBDIR}/requires/$origin/pkgtag" 2> /dev/null` || :
+               pkgtag=`cat "${DBDIR}/moved_from/$origin/pkgtag" 2> /dev/null` || :
                val=on
-               grep -q '^'`str_escape_regexp "$origin"`'$' "$dst_unselected" 2> /dev/null && val=off
+               grep -Fxq "$origin" "$dst_unselected" 2> /dev/null && val=off
                printf '%s\t"(%s)"\t%s\n' "$origin" "$pkgtag" "$val"
        done < $src > $itemlist
        misc_dialog_checklist "$title" "$desc" "$dst_selected" "$itemlist"
-       str_escape_regexp_filter < $dst_selected | sed 's/^/^/;s/$/$/' > $grepptn
-       grep -E -v -f "$grepptn" "$src" > $dst_unselected || :
+       grep -Fx -v -f "$dst_selected" "$src" > $dst_unselected || :
 }
 
 # ============= Automatic selection of removing ports =============
 deinstall_select_auto ()
 {
-       local src dst_add dst_rem tmp_srcprev tmp_srcnew diff_removed diff_removed_ptn diff_added
+       local src dst_add dst_rem tmp_srcprev tmp_srcnew diff_removed diff_added
        src=$1
        dst_add=$2
        dst_rem=$3
        tmp_srcprev=${TMPDIR}/deinstall_select_auto:src.prev
        tmp_srcnew=${TMPDIR}/deinstall_select_auto:src.new
        diff_removed=${TMPDIR}/deinstall_select_auto:diff_removed
-       diff_removed_ptn=${TMPDIR}/deinstall_select_auto:diff_removed_ptn
-       diff_available_ptn=${TMPDIR}/deinstall_select_auto:diff_available_ptn
        diff_added=${TMPDIR}/deinstall_select_auto:diff_added
        cat "$dst_add" "$dst_rem" 2> /dev/null | sort -u > $tmp_srcprev
        cat "$src" 2> /dev/null | sort -u > $tmp_srcnew
        fileedit_manipulate_old_new_lines "$tmp_srcprev" "$tmp_srcnew" "$diff_removed" "$diff_added" || return 0
-       str_escape_regexp_filter < $diff_removed | sed 's/^/^/;s/$/$/' > $diff_removed_ptn
-       str_escape_regexp_filter < $src | sed 's/^/^/;s/$/$/' > $diff_available_ptn
-       grep -v -E -f "$diff_removed_ptn" "$dst_rem" 2> /dev/null | \
-               grep -E -f "$diff_available_ptn" > $dst_rem.tmp || :
+       grep -v -Fx -f "$diff_removed" "$dst_rem" 2> /dev/null | \
+               grep -Fx -f "$src" > $dst_rem.tmp || :
        mv "$dst_rem.tmp" "$dst_rem"
        cat "$dst_add" "$diff_added" 2> /dev/null | sort -u | \
-               grep -E -f "$diff_available_ptn" > $dst_add.tmp
+               grep -Fx -f "$src" > $dst_add.tmp || :
        mv "$dst_add.tmp" "$dst_add"
 }
 
@@ -79,22 +73,22 @@ deinstall_select_leaf_ports_to_delete ()
        elif [ ! -e "${DBDIR}/inspected_ports_only_partially" ]
        then
                case $opt_dialog_auto in
-               no)
+               no )
                        touch "$dst_selected" "$dst_unselected" "$src"
                        if [ `cat "$src" 2> /dev/null | wc -l` -gt 0 ]
                        then
                                cat "$dst_selected" "$dst_unselected" 2> /dev/null | sort -u > $tmp_srcprev
-                               diff "$tmp_srcprev" "$src" > /dev/null 2>&1 || \
+                               diff -q "$tmp_srcprev" "$src" > /dev/null 2>&1 || \
                                        deinstall_select_leaf_ports_to_delete_dialog "$src" "$dst_selected" "$dst_unselected"
                        else
                                cp /dev/null "$dst_selected"
                                cp /dev/null "$dst_unselected"
                        fi
                        ;;
-               all)
+               all )
                        deinstall_select_auto "$src" "$dst_selected" "$dst_unselected"
                        ;;
-               none)
+               none )
                        deinstall_select_auto "$src" "$dst_unselected" "$dst_selected"
                        ;;
                esac
@@ -104,11 +98,10 @@ deinstall_select_leaf_ports_to_delete ()
 # ============= Dialog for selection of removing obsolete ports =============
 deinstall_select_obsolete_ports_to_delete_dialog ()
 {
-       local src dst_selected dst_unselected grepptn itemlist title desc
+       local src dst_selected dst_unselected itemlist title desc
        src=$1
        dst_selected=$2
        dst_unselected=$3
-       grepptn=${TMPDIR}/deinstall_select_obsolete_ports_to_delete_dialog::grep
        itemlist=${TMPDIR}/deinstall_select_obsolete_ports_to_delete_dialog::itemlist
        title='Obsolete packages to be deleted'
        desc='Unchecked ones are preserved.\nCancellation means to preserve all.'
@@ -116,12 +109,11 @@ deinstall_select_obsolete_ports_to_delete_dialog ()
        do
                pkgtag=`cat "${DBDIR}/initial/$origin/installed_version"`
                val=on
-               grep -q '^'`str_escape_regexp "$origin"`'$' "$dst_unselected" 2> /dev/null && val=off
+               grep -Fxq "$origin" "$dst_unselected" 2> /dev/null && val=off
                printf '%s\t"(%s)"\t%s\n' "$origin" "$pkgtag" "$val"
        done < $src > $itemlist
        misc_dialog_checklist "$title" "$desc" "$dst_selected" "$itemlist"
-       str_escape_regexp_filter < $dst_selected | sed 's/^/^/;s/$/$/' > $grepptn
-       grep -E -v -f "$grepptn" "$src" > $dst_unselected || :
+       grep -Fx -v -f "$dst_selected" "$src" > $dst_unselected || :
 }
 
 # ============= Selection of removing obsolete ports =============
@@ -144,35 +136,35 @@ deinstall_select_obsolete_ports_to_delete ()
                deinstall_select_obsolete_ports_to_delete_dialog "$src" "$dst_selected" "$dst_unselected"
        else
                case $opt_dialog_auto in
-               no)
+               no )
                        touch "$dst_selected" "$dst_unselected" "$src"
                        if [ `cat "$src" 2> /dev/null | wc -l` -gt 0 ]
                        then
                                cat "$dst_selected" "$dst_unselected" 2> /dev/null | sort -u > $tmp_srcprev
-                               diff "$tmp_srcprev" "$src" > /dev/null 2>&1 || \
+                               diff -q "$tmp_srcprev" "$src" > /dev/null 2>&1 || \
                                        deinstall_select_obsolete_ports_to_delete_dialog "$src" "$dst_selected" "$dst_unselected"
                        else
                                cp /dev/null "$dst_selected"
                                cp /dev/null "$dst_unselected"
                        fi
                        ;;
-               all)
+               all )
                        deinstall_select_auto "$src" "$dst_selected" "$dst_unselected"
                        ;;
-               none)
+               none )
                        deinstall_select_auto "$src" "$dst_unselected" "$dst_selected"
                        ;;
                esac
        fi
 }
 
-# ============= Restoration of a package for an origin =============
+# ============= Restoration of a package for a flavored origin =============
 deinstall_restore ()
 {
        local origin tmp_forbidden currentpkg backup_pkg pkg
        origin=$1
        tmp_forbidden=${TMPDIR}/deinstall_restore:forbidden
-       pkg_info_eO "$origin" && return
+       pkgsys_exists_from_orig "$origin" && return
        backup_pkg=`pkgsys_get_backup_pkg "$origin"` || return 0
        currentpkg=`pkgsys_pkgarc_to_pkgname "$backup_pkg"`
        message_stage_title "$PROGRAM_STEP_COUNTER $origin ($currentpkg)"
@@ -213,15 +205,15 @@ deinstall_restore ()
        message_echo
 }
 
-# ============= Deinstallation of a package for an origin =============
+# ============= Deinstallation of a package for a flavored origin =============
 deinstall_exec ()
 {
        local origin origin_regexp currentpkg backup_pkgdir backup_pkg pkg
        origin=$1
        origin_regexp=`str_escape_regexp "$origin"`
-       grep -v -E "^${origin_regexp}[[:space:]]" "${DBDIR}/deleted_conflicts" > ${DBDIR}/deleted_conflicts.tmp || :
+       grep -v -E "^${origin_regexp}[[:space:]]" "${DBDIR}/deleted_conflicts" > ${DBDIR}/deleted_conflicts.tmp 2> /dev/null || :
        mv "${DBDIR}/deleted_conflicts.tmp" "${DBDIR}/deleted_conflicts"
-       currentpkg=`pkg_info_qO "$origin" 2> /dev/null | tr '\n' ' ' | sed 's/ *$//'`
+       currentpkg=`pkgsys_get_installed_pkg_from_origin "$origin" | tr '\n' ' ' | sed 's/ *$//'`
        [ -n "$currentpkg" ] || return 0
        temp_set_msg_current_stage "a ${_MSG_CURRENT_STAGE_general} process for $origin ($currentpkg) $PROGRAM_STEP_COUNTER"
        database_query_get_target_attributes currentorigin "$origin"
@@ -257,7 +249,7 @@ deinstall_exec ()
                else
                        backup_pkgdir=${PKGREPOSITORY}
                fi
-               [ -d "$backup_pkgdir" ] || mkdir -p "$backup_pkgdir"
+               mkdir -p "$backup_pkgdir"
                pkg=`echo "$currentpkg" | tr ' ' '\n' | grep -v '^$' | tail -n 1`
                backup_pkg=`pkgsys_create_backup_pkg "$pkg" "$backup_pkgdir"` || :
                if [ -n "$backup_pkg" ]
index 7fe20b3..a5d8b86 100644 (file)
@@ -2,42 +2,40 @@
 # ==============================================================================
 # portsreinstall library script
 # - Editing operations on files -
-# Copyright (C) 2013-2017 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# Copyright (C) 2013-2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
 # This software is distributed under the 2-Clause BSD License.
 # ==============================================================================
 
 # ============= Remove lines exactly matching a string from a file =============
 fileedit_rm_a_line ()
 {
-       local item dstpath tmpfile pattern
+       local item dstpath tmpfile
        item=$1
        dstpath=$2
        [ -n "$item" ] || return 0
        [ -e "$dstpath" ] || return 0
        tmpfile=$dstpath.fileedit_rm_a_line.tmp
-       pattern=`str_escape_regexp "$item"`
-       grep -v -E "^$pattern$" "$dstpath" 2> /dev/null > $tmpfile || :
+       grep -v -Fx "$item" "$dstpath" 2> /dev/null > $tmpfile || :
        mv "$tmpfile" "$dstpath"
 }
 
 # ============= Add a line to a file if no matching one exists in the file =============
 fileedit_add_a_line_if_new ()
 {
-       local item dstpath tmpfile pattern dstdir
+       local item dstpath tmpfile dstdir
        item=$1
        dstpath=$2
        [ -n "$item" ] || return 0
        [ -n "$dstpath" ] || return 0
        tmpfile=$dstpath.fileedit_add_a_line_if_new.tmp
-       pattern=`str_escape_regexp "$item"`
        if [ -e "$dstpath" ]
        then
                cp "$dstpath" "$tmpfile"
-               grep -q -E "^$pattern$" "$dstpath" \
+               grep -q -Fx "$item" "$dstpath" \
                        || echo "$item" >> $tmpfile
        else
                dstdir=`dirname "$dstpath"`
-               [ -d "$dstdir" ] || mkdir -p "$dstdir"
+               mkdir -p "$dstdir"
                echo "$item" > $tmpfile
        fi
        mv "$tmpfile" "$dstpath"
@@ -79,7 +77,7 @@ fileedit_add_lines_if_new ()
        then
                while read origin
                do
-                       grep -q -E "^`str_escape_regexp \"$origin\"`$" "$dstpath" \
+                       grep -q -Fx "$origin" "$dstpath" \
                                || echo "$origin"
                done > $tmpclip
                if [ "@$advance" = @advance ]
@@ -90,7 +88,7 @@ fileedit_add_lines_if_new ()
                fi > $tmpfile
        else
                dstdir=`dirname "$dstpath"`
-               [ -d "$dstdir" ] || mkdir -p "$dstdir"
+               mkdir -p "$dstdir"
                cat > $tmpfile
        fi
        mv "$tmpfile" "$dstpath"
diff --git a/lib/libmain.sh b/lib/libmain.sh
new file mode 100644 (file)
index 0000000..05f3851
--- /dev/null
@@ -0,0 +1,532 @@
+#!/bin/sh -e
+# ==============================================================================
+# portsreinstall library script
+# - Common functions of main programs -
+# Copyright (C) 2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# This software is distributed under the 2-Clause BSD License.
+# ==============================================================================
+
+# ============= Define the software version =============
+main_set_version ()
+{
+       MYVERSION=4.0.0
+       COMPATIBLE_VERSIONS='^(4\.[0]\.[0])$'
+       # Template for development versions
+       MYVERSION=3.3.2+toward_4.0.0_20180629133501
+       COMPATIBLE_VERSIONS='^(4\.[0]\.[0]|3\.[1-3]\.[0-9]+(|\+toward_4\.[0]\.[0]+_[0-9]+))$'
+}
+
+# ============= Parse options, arguments and control parameters =============
+# All arguments/options of the main program must be passed.
+main_parse_options_arguments ()
+{
+       # ============= Save arguments for upgraded restart =============
+       options_dump_args "$@" > ${TMPDIR}/restart_command.sh
+
+       # ============= Option check =============
+       options_set_default
+
+       options_getopts "$@" || :
+       if [ $OPTIONS_ERRNO -eq 2 ]
+       then
+               message_echo "INTERNAL ERROR: In parsing options" >&2
+               exit 1
+       fi
+       shift "${OPTIONS_SHIFT}"
+       
+       options_regularize
+
+       # ============= Argument check for no-command options =============
+       if [ $opt_help_mode -ne 0 -o $opt_show_version = yes ]
+       then
+               if [ $# -gt 0 ]
+               then
+                       OPTIONS_ERRNO=1
+               fi
+       fi
+
+       # ============= Output usage if the case of a help mode or option/argument errors =============
+       if [ $OPTIONS_ERRNO -ne 0 ]
+       then
+               exit $OPTIONS_ERRNO
+       elif [ $opt_help_mode -eq 1 ]
+       then
+               usage_short
+               exit
+       elif [ $opt_help_mode -eq 2 ]
+       then
+               usage_long | less -r
+               exit
+       fi
+
+       # ============= Output version number =============
+       if [ $opt_show_version = yes ]
+       then
+               message_version
+               exit
+       fi
+
+       # ============= Set up variables for environment of ports and packages =============
+       conf_setup_ports_envs
+       conf_setup_packages_envs
+
+       # ============= Execute command operations before getting the temporary database ready =============
+       command_all_exec_before_db_creation "$@"
+
+       # ============= Creation of temporary database directory =============
+       database_maintain_create
+
+       # ============= Argument check for conventional runs =============
+       command_all_parse_args "$@"
+       shift "${COMMAND_SHIFT}"
+}
+
+# ============= Define the common termination messages =============
+main_define_common_termination_messages ()
+{
+       temp_terminate_process_common ()
+       {
+               local errno msg_where
+               errno=${1:-0}
+               [ $opt_batch_mode = yes -o $errno -eq 0 ] && return
+               msg_where=`temp_get_msg_current_stage`
+               [ -n "$msg_where" ] && msg_where=" during $msg_where"
+               message_echo
+               if [ $errno -eq 130 ]
+               then
+                       message_echo "INFO: Terminated at `message_timestamp`$msg_where."
+                       message_echo
+                       message_echo " You can restart this process from the terminated point by"
+               else
+                       message_echo "INFO: Aborted at `message_timestamp`$msg_where."
+                       message_echo
+                       message_echo " You may restart this process from the aborted point by"
+               fi
+               message_echo "executing without options or arguments as:"
+               if [ -n "$COMMAND_RESTART" ]
+               then
+                       message_echo "  ${APPNAME} $COMMAND_RESTART"
+               else
+                       message_echo "  ${APPNAME}"
+               fi
+       }
+}
+
+# ============= Set termination messages for special commands =============
+main_set_termination_messages_special ()
+{
+       temp_terminate_process ()
+       {
+               local errno tmp_msg
+               errno=${1:-0}
+               tmp_msg=${TMPDIR}/temp_terminate_process:msg
+               [ $errno -eq 0 -o $opt_batch_mode = yes ] && return
+               temp_terminate_process_common "$errno"
+               [ -n "$COMMAND_RESTART" ] && return
+               cat > $tmp_msg << eof
+Instead, if you only want to construct the temporary database so as to stop before the actual reinstallation, execute as:
+${APPNAME} prepare
+eof
+               message_cat "$tmp_msg"
+       }
+}
+
+# ============= Option settings =============
+main_option_settings ()
+{
+       local optcomb_err
+       # Load, renew and save option values
+       optcomb_err=0
+       if [ \( "x$opt_reload_conf" = xyes -o "x$opt_reset_targets" = xyes \) -a "x$COMMAND_MODE" != xredo ]
+       then
+               message_echo "ERROR: Options -L and -N are available only in the initial run of redo command." >&2
+               message_echo >&2
+               optcomb_err=1
+       fi
+       if [ "x$opt_batch_ports_only" = xyes -a "x$opt_interactive_ports_only" = xyes ]
+       then
+               message_echo "ERROR: Options -A and -I conflict with each other." >&2
+               message_echo >&2
+               optcomb_err=1
+       fi
+       if [ -e "${DBDIR}/saved_options.sh" ]
+       then
+               options_chk_invalid_optvals_renewal non_renewable || optcomb_err=$?
+               {
+                       options_renewed_optvals M renewable_anytime || optcomb_err=$?
+                       options_renewed_optvals N renewable_in_redo_on_target || optcomb_err=$?
+                       options_renewed_optvals L renewable_in_redo_on_conf || optcomb_err=$?
+               } > ${TMPDIR}/renewed_optvals.sh
+               [ $optcomb_err -eq 0 ] || exit $optcomb_err
+               . "${DBDIR}/saved_options.sh"
+               . "${TMPDIR}/renewed_optvals.sh"
+       fi
+       misc_is_superuser_privilege && misc_get_all_vardefs | options_filter saved > ${DBDIR}/saved_options.sh
+       :
+}
+
+# ============= Save the previous configuration if exists =============
+main_save_prev_conf ()
+{
+       local PROGRAM_DEPENDS
+       PROGRAM_DEPENDS=''
+       _program_exec_and_record_completion__operation ()
+       {
+               rm -rf "${DBDIR}/conf.prev"
+               [ -d "${DBDIR}/conf" ] && \
+                       cp -Rp "${DBDIR}/conf" "${DBDIR}/conf.prev"
+               :
+       }
+       program_exec_and_record_completion SAVE_PREV_CONF
+}
+
+# ============= Load the saved configuration =============
+main_load_conf ()
+{
+       . "${DBDIR}/conf/setenv.sh"
+}
+
+# ============= Get complete configuration variable definitions by importing pkgtools.conf(5) if available =============
+main_get_complete_conf ()
+{
+       local PROGRAM_DEPENDS
+       PROGRAM_DEPENDS='SAVE_PREV_CONF'
+       _program_exec_and_record_completion__operation ()
+       {
+               local need_msg
+               need_msg=no
+               rm -rf "${DBDIR}/conf"
+               mkdir -p "${DBDIR}/conf"
+               [ "x`options_get_effective_opt_load_pkgtoolsconf 2> /dev/null`" != xno -a $opt_batch_mode = no ] \
+                       && need_msg=yes
+               [ $need_msg = yes ] && \
+                       message_section_title "Parsing pkgtools.conf (by using installed portupgrade)"
+               conf_get_complete_var_defs > ${DBDIR}/conf/complete_setup.sh
+               [ $need_msg = yes ] &&  { message_echo "===> ok"; message_echo; }
+               :
+       }
+       program_exec_and_record_completion GET_COMPLETE_CONF_VAR_DEF
+}
+
+# ============= Parse the configuration =============
+main_parse_conf ()
+{
+       local PROGRAM_DEPENDS
+       PROGRAM_DEPENDS='GET_COMPLETE_CONF_VAR_DEF'
+       _program_exec_and_record_completion__operation ()
+       {
+               message_section_title "Parsing the configuration"
+               conf_manipulate_available_var_defs
+               . "${DBDIR}/conf/manipulated_defs.sh"
+               # ALT_MOVED_*
+               conf_build_effective_MOVED
+               # Environmental variables
+               conf_setup_effective_env > ${DBDIR}/conf/setenv.sh
+               . "${DBDIR}/conf/setenv.sh"
+               # HOLD_*
+               conf_parse_vars_for_each_port_glob HOLD
+               # TABOO_*
+               conf_parse_vars_for_each_port_glob TABOO
+               fileedit_combine_lists "${DBDIR}/conf/TABOO:PORTS.parsed" "${DBDIR}/taboo.list" \
+                       > ${DBDIR}/taboo.all.list
+               # FREEZE_*
+               conf_parse_vars_for_each_port_glob FREEZE
+               fileedit_combine_lists "${DBDIR}/conf/FREEZE:PORTS.parsed" "${DBDIR}/freeze.list" \
+                       > ${DBDIR}/freeze.all.list
+               # NOPKG_*
+               conf_parse_vars_for_each_port_glob NOPKG
+               # REPLACE_*
+               conf_build_replacement_patterns_from_REPLACE
+               # CONFLICT_*
+               conf_parse_vars_for_each_port_glob_with_bound_val CONFLICT TARGET DEF
+               # MARG_*
+               conf_parse_vars_for_each_port_glob_with_bound_val MARG TARGET DEF
+               # MENV_*
+               conf_parse_vars_for_each_port_glob_with_bound_val MENV TARGET DEF
+               # BEFOREBUILD_*
+               conf_parse_vars_for_each_port_glob_with_bound_val BEFOREBUILD TARGET COMMAND
+               # BEFOREDEINSTALL_*
+               conf_parse_vars_for_each_port_glob_with_bound_val BEFOREDEINSTALL TARGET COMMAND
+               # AFTERINSTALL_*
+               conf_parse_vars_for_each_port_glob_with_bound_val AFTERINSTALL TARGET COMMAND
+               message_echo
+       }
+       program_exec_and_record_completion PARSE_CONF
+}
+
+# ============= Set up parameters based on options, arguments, environment =============
+main_setup_parameters ()
+{
+       # ============= Termination messages during construction of the temporary database =============
+       main_define_common_termination_messages
+       temp_reset_termination_messages_common
+       main_set_termination_messages_special
+
+       # ============= Opening title =============
+
+       message_credit
+       command_all_chk_need_opening_notice && message_opening_notice
+       message_echo
+
+       # ============= Execute command operations which do not need package tools =============
+
+       command_all_exec_without_pkgtools "$@"
+       misc_is_superuser_privilege && database_maintain_mark_use
+       # ============= Definition of environment dependent functions =============
+
+       pkgsys_def_pkgtools
+
+       # ============= Option settings =============
+
+       # Execute command operations which are not affected by saved option settings
+       command_all_exec_irrespective_of_saved_options "$@"
+
+       # Load, renew and save option values
+       main_option_settings
+
+       # Show option values
+       message_show_option_settings
+
+       # ============= Configurations =============
+
+       # Save the previous configuration if exists
+       main_save_prev_conf
+
+       # Get complete configuration variable definitions by importing pkgtools.conf(5) if available
+       main_get_complete_conf
+
+       # Parse the configuration
+       main_parse_conf
+
+       # Load the saved configuration
+       main_load_conf
+}
+
+# ============= Operation without packages management tools =============
+main_operation_without_pkg_management_tools ()
+{
+       # Execute command operations which should be done without upgrade of tools
+       command_all_exec_before_tools_upgrade "$@"
+
+       # Check whether the temporary database is newer than the ports tree and refresh if so
+       database_maintain_refresh_if_obsolete
+}
+
+# ============= Collect all installed packages =============
+main_collect_all_installed_packages ()
+{
+       local PROGRAM_DEPENDS
+       PROGRAM_DEPENDS=''
+       _program_exec_and_record_completion__operation ()
+       {
+               local tmp_installed_ports tmp_installed_pkgs
+               message_section_title "Collecting all installed packages"
+               if [ ! -e "${DBDIR}/installed_ports" ]
+               then
+                       pkg_info_all_flavored_origins > ${DBDIR}/installed_ports.tmp
+                       pkg_info_gen_pkg_origin_table
+                       mv "${DBDIR}/installed_ports.tmp" "${DBDIR}/installed_ports"
+               fi
+               message_echo
+       }
+       program_exec_and_record_completion COLLECT_ALL_INSTALLED_PACKAGES
+}
+
+# ============= Preliminary inspection of tools which have to be up-to-date =============
+# (No need depend on PARSE_CONF because INSPECT_ALL_DEPENDENCIES will take the task.)
+main_preliminary_inspection_of_tools ()
+{
+       local PROGRAM_DEPENDS
+       PROGRAM_DEPENDS=
+       _program_exec_restartable_loop_operation__routine ()
+       {
+               local origin
+               origin=$1
+               database_build_inspect_dependencies "$origin"
+       }
+       _program_exec_and_record_completion__operation ()
+       {
+               local DEPTH_INDEX
+               message_section_title "Preliminary inspection of tools which have to be up-to-date"
+               {
+                       [ "$PKGSYS_USE_PKGNG" = yes ] && pkgsys_portsmgmt_pkg
+                       pkgsys_is_dialog4ports_used && pkgsys_portsmgmt_dialog4ports
+                       [ -n "$MYPORTORIGIN" ] && echo "$MYPORTORIGIN"
+               } 2> /dev/null > ${DBDIR}/stage.loop_list/tools_to_inspect
+               cp /dev/null "${DBDIR}/done_required_ports_to_inspect"
+               DEPTH_INDEX='--'
+               program_exec_restartable_loop_operation tools_to_inspect
+               database_build_post_inspect_dependencies
+               message_echo
+       }
+       program_exec_and_record_completion PRELIMINARY_INSPECTION_OF_TOOLS
+}
+
+# ============= Upgrade of pkg(8) if new =============
+# (No need depend on PARSE_CONF because REINSTALLATION will take the task.)
+main_upgrade_pkg8_if_new ()
+{
+       local PROGRAM_DEPENDS
+       if [ \( "$COMMAND_MODE" = do -o "$COMMAND_MODE" = redo \) \
+               -a $opt_dry_run = no -a $opt_suppress_pkgtools_upadte = no \
+               -a "$PKGSYS_USE_PKGNG" = yes ]
+       then
+               PROGRAM_DEPENDS='PRELIMINARY_INSPECTION_OF_TOOLS'
+               _program_exec_and_record_completion__operation ()
+               {
+                       local _MSG_CURRENT_STAGE_general
+                       _MSG_CURRENT_STAGE_general="pkg(8) upgrade"
+                       temp_set_msg_current_stage "${_MSG_CURRENT_STAGE_general}"
+                       message_section_title "Upgrade of `pkgsys_portsmgmt_pkg` if new"
+                       touch "${DBDIR}/target_all"
+                       reinstall_exec `pkgsys_portsmgmt_pkg`
+                       reinstall_restore_conflicts
+                       rm -f "${DBDIR}/target_all"
+                       temp_set_msg_current_stage
+                       message_echo
+               }
+               program_exec_and_record_completion UPGRADE_PKGNG
+       fi
+}
+
+# ============= Upgrade of dialog4ports(1) if new =============
+# (No need depend on PARSE_CONF because REINSTALLATION will take the task.)
+main_upgrade_dialog4ports1_if_new ()
+{
+       local PROGRAM_DEPENDS
+       if [ \( "$COMMAND_MODE" = do -o "$COMMAND_MODE" = redo \) \
+               -a $opt_dry_run = no -a $opt_suppress_pkgtools_upadte = no ] \
+               && pkgsys_is_dialog4ports_used
+       then
+               PROGRAM_DEPENDS='PRELIMINARY_INSPECTION_OF_TOOLS'
+               _program_exec_and_record_completion__operation ()
+               {
+                       local _MSG_CURRENT_STAGE_general
+                       _MSG_CURRENT_STAGE_general="dialog4ports(1) upgrade"
+                       temp_set_msg_current_stage "${_MSG_CURRENT_STAGE_general}"
+                       message_section_title "Upgrade of `pkgsys_portsmgmt_dialog4ports` if new"
+                       touch "${DBDIR}/target_all"
+                       reinstall_exec `pkgsys_portsmgmt_dialog4ports`
+                       reinstall_restore_conflicts
+                       rm -f "${DBDIR}/target_all"
+                       temp_set_msg_current_stage
+                       message_echo
+               }
+               program_exec_and_record_completion UPGRADE_DIALOG4PORTS
+       fi
+}
+
+# ============= Upgrade of this utility if new =============
+# (No need depend on PARSE_CONF because REINSTALLATION will take the task.)
+main_self_upgrade ()
+{
+       local PROGRAM_DEPENDS
+       if [ \( "$COMMAND_MODE" = do -o "$COMMAND_MODE" = redo \) \
+               -a $opt_dry_run = no -a $opt_suppress_self_upadte = no \
+               -a -n "$MYPORTORIGIN" ]
+       then
+               PROGRAM_DEPENDS='PRELIMINARY_INSPECTION_OF_TOOLS'
+               _program_exec_and_record_completion__operation ()
+               {
+                       local _MSG_CURRENT_STAGE_general
+                       _MSG_CURRENT_STAGE_general="pkgng upgrade"
+                       temp_set_msg_current_stage "${_MSG_CURRENT_STAGE_general}"
+                       message_section_title "Upgrade of this utility if new"
+                       touch "${DBDIR}/target_all"
+                       reinstall_exec "$MYPORTORIGIN"
+                       reinstall_restore_conflicts
+                       rm -f "${DBDIR}/target_all"
+                       temp_set_msg_current_stage
+                       message_echo
+               }
+               program_exec_and_record_completion UPGRADE_SELF
+       fi
+       if [ "x`${APPNAME} -aV 2> /dev/null`" != "x$MYVERSION" ]
+       then
+               message_echo "INFO: ${APPNAME} is upgraded and the temporary database needs refresh."
+               database_maintain_clean_for_self_upgrade || :
+               message_echo "INFO: Restarting with the new version."
+               message_echo
+               temp_trap_for_invoking_new_version
+               . "${TMPDIR}"/restart_command.sh
+               exit
+       fi
+}
+
+# ============= Overlay onto the temporary database by reflecting changes in configuration =============
+main_reflect_conf_changes ()
+{
+       local PROGRAM_DEPENDS
+       PROGRAM_DEPENDS='PARSE_CONF'
+       _program_exec_and_record_completion__operation ()
+       {
+               local tmpfile_diff tmpfile_old tmpfile_new key
+               [ -d "${DBDIR}/conf.prev" ] || return 0
+               message_section_title "Overlay onto the temporary database by reflecting changes in configuration"
+               tmpfile_old=${TMPDIR}/PATCH_TO_TMPDB_REFLECT_CONF_CHANGES::old
+               tmpfile_new=${TMPDIR}/PATCH_TO_TMPDB_REFLECT_CONF_CHANGES::new
+               tmpfile_updated_ports=${TMPDIR}/PATCH_TO_TMPDB_REFLECT_CONF_CHANGES::updated_ports
+               if fileedit_manipulate_old_new_lines \
+                       "${DBDIR}/conf.prev/setenv.sh" "${DBDIR}/conf/setenv.sh" "$tmpfile_old" "$tmpfile_new"
+               then
+                       if grep -q -e ^LOCALBASE= -e ^LINUXBASE= -e ^PORTSDIR= "$tmpfile_old" "$tmpfile_new"
+                       then
+                               message_echo "ERROR: Migration of the temporary database is unavailable because LOCALBASE, LINUXBASE or PORTSDIR was changed." >&2
+                               message_echo "        ${APPNAME} clean" >&2
+                               message_echo "must be executed in advance." >&2
+                               exit 1
+                       fi
+               fi
+               cut -s -d '|' -f 1,2 "${DBDIR}/conf.prev/MOVED_ALT.parsed" | tr '|' '\t' > ${TMPDIR}/MOVED_ALT.old
+               cut -s -d '|' -f 1,2 "${DBDIR}/conf/MOVED_ALT.parsed" | tr '|' '\t' > ${TMPDIR}/MOVED_ALT.new
+               if fileedit_manipulate_old_new_lines \
+                       "${TMPDIR}/MOVED_ALT.old" "${TMPDIR}/MOVED_ALT.new" "$tmpfile_old" "$tmpfile_new"
+               then
+                       cat "$tmpfile_old" "$tmpfile_new" | while read from to
+                       do
+                               echo "$from"
+                               [ -n "$to" ] && echo "$to"
+                       done
+               fi > $tmpfile_updated_ports
+               sort -u "${DBDIR}/conf/NOPKG:PORTS.parsed" 2> /dev/null > ${TMPDIR}/NOPKG:PORTS.parsed.new || :
+               sort -u "${DBDIR}/conf.prev/NOPKG:PORTS.parsed" 2> /dev/null > ${TMPDIR}/NOPKG:PORTS.parsed.old || :
+               diff "${TMPDIR}/NOPKG:PORTS.parsed.old" "${TMPDIR}/NOPKG:PORTS.parsed.new" | sed -n 's/^[<>] //p' >> $tmpfile_updated_ports
+               if fileedit_manipulate_old_new_lines \
+                       "${DBDIR}/conf.prev/REPLACE.csv" "${DBDIR}/conf/REPLACE.csv" "$tmpfile_old" "$tmpfile_new"
+               then
+                       cat "$tmpfile_old" "$tmpfile_new" | while read from to
+                       do
+                               echo "$from"
+                               [ -n "$to" ] && echo "$to"
+                       done
+               fi >> $tmpfile_updated_ports
+               [ `wc -l < $tmpfile_updated_ports` -gt 0 ] && rm -f "${DBDIR}/REPLACE.complete_sed_pattern"
+               [ -d "${DBDIR}/conf/each_port" ] && find "${DBDIR}/conf/each_port" -depth 2 \
+                       | while read dbpath
+               do
+                       origin=`str_dirpath_to_origin "$dbpath"`
+                       dbpath_prev=${DBDIR}/conf.prev/each_port/$origin
+                       diff -r "$dbpath_prev" "$dbpath" > /dev/null 2>&1 && continue
+                       echo "$origin"
+               done >> $tmpfile_updated_ports
+               [ -d "${DBDIR}/conf.prev/each_port" ] && find "${DBDIR}/conf.prev/each_port" -depth 2 \
+                       | while read dbpath_prev
+               do
+                       origin=`str_dirpath_to_origin "$dbpath_prev"`
+                       dbpath=${DBDIR}/conf/each_port/$origin
+                       [ -d "$dbpath" ] && continue
+                       echo "$origin"
+               done >> $tmpfile_updated_ports
+               if [ `wc -l < $tmpfile_updated_ports` -gt 0 ]
+               then
+                       sort -u "$tmpfile_updated_ports" | while read origin
+                       do
+                               database_build_patch_reconf "$origin"
+                       done
+                       program_deregister_stage_complete INSPECT_ALL_DEPENDENCIES
+                       program_deregister_stage_complete ALL_COMPLETE
+               fi
+               message_echo
+       }
+       program_exec_and_record_completion PATCH_TO_TMPDB_REFLECT_CONF_CHANGES
+}
index b3d200a..d26b11f 100644 (file)
@@ -2,7 +2,7 @@
 # ==============================================================================
 # portsreinstall library script
 # - Messages -
-# Copyright (C) 2013-2017 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# Copyright (C) 2013-2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
 # This software is distributed under the 2-Clause BSD License.
 # ==============================================================================
 
 message_query_yn_default_yes ()
 {
        local answer
+       [ $opt_batch_mode = yes ] && return 0
        read answer || :
        case `echo "$answer" | head -c 1` in
-       y|Y)    message_echo
+       y | Y ) message_echo
                return 0
                ;;
-       n|N)    message_echo
+       n | N ) message_echo
                return 1
                ;;
-       ''    return 0
+       '' )    return 0
                ;;
        *)      message_echo
                message_echo 'Pardon? ([y]/n)'
@@ -31,15 +32,16 @@ message_query_yn_default_yes ()
 message_query_yn_default_no ()
 {
        local answer
+       [ $opt_batch_mode = yes ] && return 1
        read answer || :
        case `echo "$answer" | head -c 1` in
-       y|Y)    message_echo
+       y | Y ) message_echo
                return 0
                ;;
-       n|N)    message_echo
+       n | N ) message_echo
                return 1
                ;;
-       ''    return 1
+       '' )    return 1
                ;;
        *)      message_echo
                message_echo 'Pardon? (y/[n])'
@@ -55,10 +57,19 @@ message_version ()
        echo "${MYVERSION}"
 }
 
+# ============= Output the brief description =============
+message_brief_description ()
+{
+       cat << eof
+ -- Ports upgrading utility for massive forced reinstallation
+ -- And for those who are pursuing the perfect packages environment
+eof
+}
+
 # ============= Output a message except for the batch mode =============
 message_echo ()
 {
-       [ "x$opt_batch_mode" = xyes ] && return
+       [ $opt_batch_mode = yes ] && return
        echo "$@" | fold -s -w `misc_get_console_column_size`
 }
 
@@ -67,7 +78,7 @@ message_echo ()
 message_cat ()
 {
        local ncolumns
-       [ "x$opt_batch_mode" = xyes ] && return
+       [ $opt_batch_mode = yes ] && return
        ncolumns=`misc_get_console_column_size`
        fold -s -w $ncolumns "$@"
 }
@@ -76,13 +87,12 @@ message_cat ()
 message_credit ()
 {
        local ncolumns
-       [ "x$opt_batch_mode" = xyes ] && return
+       [ $opt_batch_mode = yes -o "x$opt_no_opening_message" = xyes ] && return
        ncolumns=`misc_get_console_column_size`
        message_version | fold -s -w $ncolumns
+       message_brief_description | fold -s -w $ncolumns
        fold -s -w $ncolumns << eof
- -- Ports upgrading utility for massive forced reinstallation
- -- And for those who are pursuing the perfect packages environment
-Copyright (C) 2010 - 2015 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+Copyright (C) 2010 - 2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
 Email: <sakaue.mamoru@samurai.mwghennn.net>
 Homepage: <http://www.mwghennndo.com/software/portsreinstall/>
 eof
@@ -98,7 +108,7 @@ message_timestamp ()
 message_opening_notice ()
 {
        local ncolumns
-       [ "x$opt_batch_mode" = xyes ] && return
+       [ $opt_batch_mode = yes -o $opt_no_opening_message = yes ] && return
        ncolumns=`misc_get_console_column_size`
        fold -s -w $ncolumns << eof
 
@@ -108,6 +118,21 @@ message_opening_notice ()
 eof
 }
 
+# ============= Show option settings =============
+message_show_option_settings ()
+{
+       if [ -e "${DBDIR}/saved_options.sh" \
+               -a $opt_batch_mode = no -a $opt_no_opening_message = no \
+               -a \( $COMMAND_MODE = do -o $COMMAND_MODE = redo \) ]
+       then
+               message_echo "INFO: List of option values:"
+               message_echo "-----------------------------------------"
+               message_cat "${DBDIR}/saved_options.sh"
+               message_echo "-----------------------------------------"
+               message_echo
+       fi
+}
+
 # ============= Report a failure in a process for a port =============
 message_report_failure_for_a_port ()
 {
@@ -120,7 +145,7 @@ message_report_failure_for_a_port ()
 # ============= Output the relation of the current port with specified targets =============
 message_target_relations ()
 {
-       [ "x$opt_batch_mode" = xyes ] && return
+       [ $opt_batch_mode = yes ] && return
        ( set -e
                origin=$1
                database_query_get_target_attributes it "$origin"
@@ -160,7 +185,7 @@ message_stage_title ()
        message_echo "[At `message_timestamp`]"
 }
 
-# ============= Dummy output for dry run =============
+# ============= Message of dry run =============
 message_dry_run ()
 {
        message_echo "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
@@ -169,6 +194,15 @@ message_dry_run ()
        message_echo
 }
 
+# ============= Message of fetch-only mode =============
+message_fetch_only ()
+{
+       message_echo "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
+       message_echo "@@@@@@@@@@@@@ FETCH-ONLY MODE @@@@@@@@@@@@@"
+       message_echo "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
+       message_echo
+}
+
 # ============= Output a summary of a resource recorded in a list =============
 message_summary_dependents_of_failed_reinstallation ()
 {
@@ -239,12 +273,9 @@ eof
 # ============= Output a warning if no progress was achieved =============
 message_warn_no_achieved_progress ()
 {
-       [ `cat "${DBDIR}/new_success_in_current_run" 2> /dev/null | wc -l` -gt 0 ] && return
-       [ $opt_batch_mode = yes ] && return 1
+       [ $opt_batch_mode = yes ] && return
        message_echo '****************'
-       message_echo "WARNING: No progress was achieved by this run."
-       message_echo "         Manual solution is needed on the failed ports."
+       message_echo "WARNING: Some problems remain. Manual troubleshooting is required."
        message_echo '****************'
        message_echo
-       return 1
 }
index bc4b8aa..f5570e7 100644 (file)
@@ -2,7 +2,7 @@
 # ==============================================================================
 # portsreinstall library script
 # - Miscellaneous functions -
-# Copyright (C) 2013-2017 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# Copyright (C) 2013-2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
 # This software is distributed under the 2-Clause BSD License.
 # ==============================================================================
 
@@ -36,11 +36,12 @@ misc_lock_duplicated_executions ()
        :
 }
 
-# ============= Check the superuser privilege and abort if not =============
+# ============= Abort if the execution is locked or the user does not have the superuser privilege =============
 misc_chk_privilege ()
 {
        misc_is_superuser_privilege && return
-       message_echo "ERROR: The superuser privilege is required for this command." >&2
+       [ "$MISC_IS_READONLY_MODE" = yes ] && message_echo "ERROR: Locked for this command." >&2
+       [ `id -u` -ne 0 ] && message_echo "ERROR: The superuser privilege is required for this command." >&2
        exit 1
 }
 
@@ -90,6 +91,191 @@ misc_get_console_row_size ()
        misc_get_console_size | sed -E 's/^([^ ]+) +[^ ]+/\1/'
 }
 
+# ============= Get the global path of a possibly not yet created file/directory =============
+misc_global_path ()
+{
+       local $path_src
+       path_src=$1
+       if [ -e "$path_src" ]
+       then
+               realpath "$path_src"
+       else
+               expr "$path_src" : '^/' > /dev/null || echo -n `realpath .`
+               echo "$path_src"
+       fi
+}
+
+# ============= Inspect the privilege of the current environment on file system operation =============
+misc_inspect_fs_privilege ()
+{
+       local tgv mp mp_regexp mount_privilege basedir
+       [ -d "${TMPDIR}"/fs_privilege ] && return
+       tgv=${TMPDIR}/fs_privilege/test_tg
+       mkdir -p "$tgv" "${TMPDIR}"/fs_privilege/test_mp
+       mp=`realpath "${TMPDIR}"/fs_privilege/test_mp`
+       mp_regexp=`str_escape_regexp "$mp"`
+       echo yes > ${TMPDIR}/fs_privilege/fs_privilege
+       cat > ${TMPDIR}/fs_privilege/fslist << eof
+devfs  devfs
+fdescfs        null
+procfs proc
+tmpfs  tmpfs
+nullfs "$tgv"
+unionfs        "$tgv"
+eof
+       while read fs tg
+       do
+               if mount -t $fs "$tgv" "$mp" 2> /dev/null && umount "$mp"
+               then
+                       echo yes
+               else
+                       echo no
+                       echo no > ${TMPDIR}/fs_privilege/fs_privilege
+               fi > ${TMPDIR}/fs_privilege/fs_privilege:$fs 2> /dev/null
+               umount -f "$mp" 2> /dev/null || :
+               [ -e "${TMPDIR}"/fs_privilege/basedir ] && continue
+               mount -t $fs "$tgv" "$mp" 2> /dev/null && \
+                       df "$mp" > ${TMPDIR}/fs_privilege/df:$fs && \
+                       umount "$mp"
+               real_mp=`sed 1d "${TMPDIR}"/fs_privilege/df:$fs | tail -n 1 | \
+                       sed -E 's/^.*[[:space:]][0-9]+%[[:space:]]+//'`
+               echo "$real_mp" | sed -E "s/$mp_regexp$//" > ${TMPDIR}/fs_privilege/basedir
+       done < ${TMPDIR}/fs_privilege/fslist
+       mount_privilege=`cat "${TMPDIR}"/fs_privilege/fs_privilege`
+       if [ "x$mount_privilege" = xyes ]
+       then
+               mount -t nullfs /bin "$mp" 2> /dev/null
+               if [ `ls "$mp" 2> /dev/null | wc -l` -gt 0 ]
+               then
+                       echo yes
+               else
+                       echo no
+               fi > ${TMPDIR}/fs_privilege/nullfs_target_recognition
+               umount -f "$mp" 2> /dev/null || :
+               nullfs_target_recognition=`cat "${TMPDIR}"/fs_privilege/nullfs_target_recognition`
+               if [ "x$nullfs_target_recognition" = xyes ]
+               then
+                       message_echo "INFO: The current environment has the full required privilege of mounting/unmounting file systems."
+               else
+                       message_echo "INFO: The current environment formally has the full required privilege of mounting/unmounting file systems but the recognition of nullfs/unionfs targets is incorrect."
+               fi
+       else
+               echo no > ${TMPDIR}/fs_privilege/nullfs_target_recognition
+               message_echo "INFO: The current environment does not have the privilege of mounting/unmounting for the following file system(s)."
+               while read fs tg
+               do
+                        mount_privilege=`cat "${TMPDIR}"/fs_privilege/fs_privilege:$fs`
+                        [ "x$mount_privilege" = xyes ] || echo '  '$fs
+               done < ${TMPDIR}/fs_privilege/fslist | message_cat
+       fi
+       basedir=`cat "${TMPDIR}"/fs_privilege/basedir 2> /dev/null || :`
+       if [ -n "$basedir" ]
+       then
+               message_echo "INFO: The current environment will be a chroot/jail guest whose base directory is \"$basedir\"."
+       fi
+       if [ "x$opt_invalidate_mount_privilege" = xyes ]
+       then
+               message_echo "INFO: The privilege of mounting/unmounting in this environment is forcibly invalidated."
+       fi
+}
+
+# ============= Check whether mounting file systems are available at the current environment =============
+misc_chk_mount_privilege ()
+{
+       local mount_privilege
+       misc_inspect_fs_privilege
+       [ "x$opt_invalidate_mount_privilege" = xno ] || return
+       mount_privilege=`cat "${TMPDIR}"/fs_privilege/fs_privilege`
+       nullfs_target_recognition=`cat "${TMPDIR}"/fs_privilege/nullfs_target_recognition`
+       [ "x$nullfs_target_recognition" = xyes -a "x$mount_privilege" = xyes ]
+}
+
+# ============= Check whether mounting file systems are available at the current environment =============
+misc_chk_unmount_privilege ()
+{
+       local mount_privilege
+       misc_inspect_fs_privilege
+       [ "x$opt_invalidate_mount_privilege" = xno ] || return
+       mount_privilege=`cat "${TMPDIR}"/fs_privilege/fs_privilege`
+       [ "x$mount_privilege" = xyes ]
+}
+
+# ============= Get the base directory the current environment (applicable in case of a chroot guest) =============
+misc_get_system_basedir ()
+{
+       misc_inspect_fs_privilege
+       cat "${TMPDIR}"/fs_privilege/basedir 2> /dev/null || :
+}
+
+# ============= Check whether the current environment is in a jail =============
+misc_chk_in_jail ()
+{
+       local status
+       status=`sysctl -n security.jail.jailed`
+       [ x"$status" != x0 ]
+}
+
+# ============= Get the regular expression pattern of the actual mount point =============
+misc_get_actual_mount_point_pattern ()
+{
+       local mountpoint basedir mountpoint_real
+       mountpoint=$1
+       [ -e  "$mountpoint" ] || return
+       misc_inspect_fs_privilege
+       basedir=`cat "${TMPDIR}"/fs_privilege/basedir 2> /dev/null || :`
+       mountpoint_real=`realpath "$mountpoint"`
+       mountpoint_real_full=`echo "$basedir$mountpoint_real" | sed 's|//*|/|'`
+       str_escape_regexp "$mountpoint_real_full"
+}
+
+# ============= Get mount info at the descendant directory levels required for builder chroot environment =============
+misc_get_descendant_mount_info ()
+{
+       local mountpoint mountpoint_real_regexp basedir
+       mountpoint=$1
+       mountpoint_real_regexp=`misc_get_actual_mount_point_pattern "$mountpoint"` || return
+       basedir=`cat "${TMPDIR}"/fs_privilege/basedir 2> /dev/null || :`
+       basedir_ptn=`str_escape_regexp "$basedir"`
+       df | sed 1d | grep -E "%[[:space:]]+$mountpoint_real_regexp\/" | while read fs data
+       do
+               echo "$fs" | grep -q -e '^/' -e '^<above>:' && fs=normal
+               mp_abs=`echo "$data" | sed -E  's|.*%[[:space:]]+(/.+)$|\1|'`
+               mp=`echo "$mp_abs" | sed -E "s|^$basedir_ptn||"`
+               relative=`echo "$mp_abs" | sed -E "s|^$mountpoint_real_regexp||"`
+               printf '%s\t%s\t%s\n' "$fs" "$mp" "$relative"
+       done
+}
+
+# ============= Check whether a directory is mounted properly =============
+misc_chk_mounted ()
+{
+       local type target mountpoint target_ptn mountpoint_real_regexp tmpsrc
+       type=$1
+       target=$2
+       mountpoint=$3
+       target_ptn=`echo "$target" | sed 's|//*|/|g' | str_escape_regexp_filter`
+       mountpoint_real_regexp=`misc_get_actual_mount_point_pattern "$mountpoint"` || return
+       basedir=`cat "${TMPDIR}"/fs_privilege/basedir 2> /dev/null || :`
+       basedir_target_ptn=`echo "$basedir/$target" | sed 's|//*|/|g' | str_escape_regexp_filter`
+       tmpsrc=${TMPDIR}/misc_chk_mounted:src
+       df | sed 1d | grep -E "%[[:space:]]+$mountpoint_real_regexp$" > $tmpsrc
+       case $type in
+               nullfs )
+                       grep -qE "^${target_ptn}[[:space:]]" "$tmpsrc" || grep -qE "^${basedir_target_ptn}[[:space:]]" "$tmpsrc"
+                       ;;
+               unionfs )
+                       grep -qE "^<above>:${target_ptn}[[:space:]]" "$tmpsrc" || grep -qE "^<above>:${basedir_target_ptn}[[:space:]]" "$tmpsrc"
+                       ;;
+               devfs | fdescfs | procfs | linprocfs | tmpfs )
+                       grep -q "^$type" "$tmpsrc"
+                       ;;
+               *)
+                       message_echo "ERROR: Unsupported fyle system [$type]" >&2
+                       exit 1
+                       ;;
+       esac
+}
+
 # ============= Selection of removing leaf ports =============
 # Box options for dialog(1) are given via stdin.
 misc_dialog_checklist ()
index 3b0c289..90c84c2 100644 (file)
@@ -1,8 +1,8 @@
 #!/bin/sh -e
 # ==============================================================================
 # portsreinstall library script
-# - Command line options -
-# Copyright (C) 2013-2017 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# - Interface of libraries for command line options -
+# Copyright (C) 2013-2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
 # This software is distributed under the 2-Clause BSD License.
 # ==============================================================================
 
@@ -17,15 +17,6 @@ OPTIONS_SHIFT=0
 options_db_onetime ()
 {
        cat << eof
-h      help    opt_help_mode   0       1
-h      short-help      opt_help_mode   0       1
-H      long-help       opt_help_mode   0       2
-V      show-version    opt_show_version        no      yes
-a      batch-mode      opt_batch_mode  no      yes
-N      reset-targets   opt_reset_targets       no      yes
-M      reset-minor-options     opt_reset_minor_options no      yes
-L      reload-conf     opt_reload_conf no      yes
-i      allow-new-targets       opt_allow_new_targets   no      yes
 eof
 }
 
@@ -33,25 +24,6 @@ eof
 options_db_saved_and_renewable ()
 {
        cat << eof
-C      apply-default-config    opt_apply_default_config        no      yes
-A      non-interactive-ports-only      opt_batch_ports_only    no      yes
-I      interactive-ports-only  opt_interactive_ports_only      no      yes
-s      avoid-vulnerability-check       opt_avoid_vulner        no      yes
-q      skip-unchanged-ports    opt_skip_unchanged      no      yes
-b      include-buildtime-dependencies  opt_include_buildtime_dependencies      no      yes
-B      exclude-runtime-dependencies    opt_include_runtime_dependencies        yes     no
-d      keep-distfiles  opt_keep_distfiles      no      yes
-k      suppress-self-upadte    opt_suppress_self_upadte        no      yes
-g      suppress-pkgtools-upadte        opt_suppress_pkgtools_upadte    no      yes
-c      suppress-clean-obsolete-database        opt_suppress_obsolete_db_clean  no      yes
-D      suppress-entire-inspection-distinfo     opt_inspect_entire_distinfo     yes     no
-n      dry-run opt_dry_run     no      yes
-X      deselect-all    opt_dialog_auto no      none
-Y      select-all      opt_dialog_auto no      all
-G      use-prebuilt-package    opt_inst_by_pkg_if_can  no      yes
-l      use-legacy-package-for-missing-pkgng    opt_use_legacy_pkg_for_missing_pkgng    no      yes
-f      disallow-force-continuation-for-looped-dependency       opt_disallow_force_continuation_for_looped_dependency   no      yes
-F      fetch-only      opt_fetch_only  no      yes
 eof
 }
 
@@ -59,10 +31,6 @@ eof
 options_db_saved_and_renewable_in_redo_on_target ()
 {
        cat << eof
-t      target-and-dependents   opt_target_dependents   ''      :
-T      target-and-requirements opt_target_requirements ''      :
-O      target-only-itself      opt_target_itself       ''      :
-o      only-target-scope       opt_only_target_scope   no      yes
 eof
 }
 
@@ -70,9 +38,6 @@ eof
 options_db_saved_and_renewable_in_redo_on_conf ()
 {
        cat << eof
-p      load-pkgtoolsconf-as-default    opt_load_pkgtoolsconf   undef   default
-P      load-pkgtoolsconf-as-override   opt_load_pkgtoolsconf   undef   override
-Q      ignore-pkgtoolsconf     opt_load_pkgtoolsconf   undef   no
 eof
 }
 
@@ -83,6 +48,11 @@ options_db_saved_and_non_renewable ()
 eof
 }
 
+# ============= Regularize the option value =============
+options_regularize ()
+{
+}
+
 # ============= Database of all options to be saved =============
 options_db_saved ()
 {
@@ -107,20 +77,27 @@ options_db ()
                while [ $# -gt 0 ]
                do
                        case $1 in
-                       renewable_anytime)
-                               options_db_saved_and_renewable;;
-                       renewable_in_redo_on_target)
-                               options_db_saved_and_renewable_in_redo_on_target;;
-                       renewable_in_redo_on_conf)
-                               options_db_saved_and_renewable_in_redo_on_conf;;
-                       non_renewable)
-                               options_db_saved_and_non_renewable;;
-                       saved)
-                               options_db_saved;;
-                       onetime)
-                               options_db_onetime;;
-                       all)
-                               options_db_all;;
+                       renewable_anytime )
+                               options_db_saved_and_renewable
+                               ;;
+                       renewable_in_redo_on_target )
+                               options_db_saved_and_renewable_in_redo_on_target
+                               ;;
+                       renewable_in_redo_on_conf )
+                               options_db_saved_and_renewable_in_redo_on_conf
+                               ;;
+                       non_renewable )
+                               options_db_saved_and_non_renewable
+                               ;;
+                       saved )
+                               options_db_saved
+                               ;;
+                       onetime )
+                               options_db_onetime
+                               ;;
+                       all )
+                               options_db_all
+                               ;;
                        *)
                                message_echo "ERROR: Invalid argument [$1] for options_inverse_parse" >&2
                                exit 1;;
@@ -339,10 +316,9 @@ options_select_new_ports_if_duplicated ()
                cp /dev/null "$tmp_new_ports"
                while read origin
                do
-                       origin_regexp=`str_escape_regexp "$origin"`
-                       if pkgsys_pkg_info_eO "$origin" \
+                       if pkgsys_exists_or_existed_from_orig "$origin" \
                                || cat "${DBDIR}/installed_ports" "${DBDIR}/targets_specified_so_far" 2> /dev/null \
-                                       | grep -q -E "$origin_regexp"
+                                       | grep -q -Fx "$origin"
                        then
                                echo "$origin" >> $tmp_existing_ports
                        else
@@ -381,14 +357,18 @@ options_select_new_ports_if_duplicated ()
 options_get_dependency_type ()
 {
        case $opt_include_buildtime_dependencies+$opt_include_runtime_dependencies in
-       yes+yes)
-               echo all;;
-       no+yes)
-               echo run;;
-       yes+no)
-               echo build;;
-       no+no)
-               echo none;;
+       yes+yes )
+               echo all
+               ;;
+       no+yes )
+               echo run
+               ;;
+       yes+no )
+               echo build
+               ;;
+       no+no )
+               echo none
+               ;;
        esac
 }
 
@@ -398,19 +378,19 @@ options_parse_dependency_type ()
        local deptag
        deptag=$1
        case $deptag in
-       all)
+       all )
                opt_include_buildtime_dependencies=yes
                opt_include_runtime_dependencies=yes
                ;;
-       run)
+       run )
                opt_include_buildtime_dependencies=no
                opt_include_runtime_dependencies=yes
                ;;
-       build)
+       build )
                opt_include_buildtime_dependencies=yes
                opt_include_runtime_dependencies=no
                ;;
-       none)
+       none )
                opt_include_buildtime_dependencies=no
                opt_include_runtime_dependencies=no
                ;;
@@ -421,10 +401,12 @@ options_parse_dependency_type ()
 options_get_dependency_level ()
 {
        case $opt_only_target_scope in
-       yes)
-               echo direct;;
-       no)
-               echo full;;
+       yes )
+               echo direct
+               ;;
+       no )
+               echo full
+               ;;
        esac
 }
 
@@ -434,10 +416,12 @@ options_parse_dependency_level ()
        local level
        level=$1
        case $level in
-       direct)
-               opt_only_target_scope=yes;;
-       full)
-               opt_only_target_scope=no;;
+       direct )
+               opt_only_target_scope=yes
+               ;;
+       full )
+               opt_only_target_scope=no
+               ;;
        esac
 }
 
@@ -447,14 +431,18 @@ options_get_dependency_msgterm ()
        local scope
        scope=`options_get_dependency_level`
        case $opt_include_buildtime_dependencies+$opt_include_runtime_dependencies in
-       yes+yes)
-               echo "$scope run- and build-time";;
-       no+yes)
-               echo "$scope run-time";;
-       yes+no)
-               echo "$scope build-time";;
-       no+no)
-               echo 'no';;
+       yes+yes )
+               echo "$scope run- and build-time"
+               ;;
+       no+yes )
+               echo "$scope run-time"
+               ;;
+       yes+no )
+               echo "$scope build-time"
+               ;;
+       no+no )
+               echo 'no'
+               ;;
        esac
 }
 
@@ -478,3 +466,54 @@ options_get_effective_opt_load_pkgtoolsconf ()
        echo "$effective_opt_load_pkgtoolsconf"
 }
 
+# ============= Show the setting of an option group =============
+options_show_group_setting ()
+{
+       local opt_control group_reset group_remain reset_opts result_opts str_opt_control str_rstoption notice_reset notice_result
+       opt_control=$1
+       group_reset=$2
+       group_remain=$3
+       reset_opts=`options_inverse_parse $group_reset`
+       result_opts=`options_inverse_parse $group_remain`
+       if [ $is_batch_mode = yes ]
+       then
+               printf '%s\t%s\t%s\n' "$opt_control" "$reset_opts" "$result_opts"
+       else
+               str_opt_control=`echo "$opt_control" | sed -E 's/(.)/-\1 /g;s/ *$//'`
+               str_rstoption=Option`[ \`echo -n "$opt_control" | wc -c\` -ge 2 ] && echo s` || :
+               notice_reset=`[ -z "$reset_opts" ] && echo ' (nothing)'` || :
+               notice_result=`[ -z "$result_opts" ] && echo ' (default)'` || :
+               echo "$str_rstoption [$str_opt_control] will reset [$reset_opts]$notice_reset so that the settings become [$result_opts]$notice_result."
+       fi
+}
+
+# ============= Show the all options =============
+options_show_all ()
+{
+               ( set -e
+                       is_batch_mode=$opt_batch_mode
+                       options_set_default
+                       [ -e "${DBDIR}/saved_options.sh" ] && . "${DBDIR}/saved_options.sh"
+                       savedopts=`options_inverse_parse`
+                       if [ $is_batch_mode = yes ]
+                       then
+                               printf '\t%s\n' "$savedopts"
+                       else
+                               echo "The saved setting is [$savedopts]."
+                       fi
+                       options_show_group_setting M \
+                               'renewable_anytime' 'non_renewable renewable_in_redo_on_target renewable_in_redo_on_conf'
+                       options_show_group_setting N \
+                               'renewable_in_redo_on_target' 'non_renewable renewable_anytime renewable_in_redo_on_conf'
+                       options_show_group_setting L \
+                               'renewable_in_redo_on_conf' 'non_renewable renewable_anytime renewable_in_redo_on_target'
+                       options_show_group_setting MN \
+                               'renewable_anytime renewable_in_redo_on_target' 'non_renewable renewable_in_redo_on_conf'
+                       options_show_group_setting ML \
+                               'renewable_anytime renewable_in_redo_on_conf' 'non_renewable renewable_in_redo_on_target'
+                       options_show_group_setting NL \
+                               'renewable_in_redo_on_target renewable_in_redo_on_conf' 'non_renewable renewable_anytime'
+                       options_show_group_setting MNL \
+                               'renewable_anytime renewable_in_redo_on_target renewable_in_redo_on_conf' 'non_renewable'
+               )
+}
index c558404..1414cc8 100644 (file)
@@ -2,16 +2,13 @@
 # ==============================================================================
 # portsreinstall library script
 # - Wrappers for hiding version differences in the Ports/Packages system -
-# Copyright (C) 2013-2017 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# Copyright (C) 2013-2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
 # This software is distributed under the 2-Clause BSD License.
 # ==============================================================================
 
 # ============= Variables =============
 PKGSYS_USE_PKGNG=yes   # no: legacy pkg_* tools, yes: the new generation package (pkgng)
-PKGSYS_CMD_PKG_INFO='pkg info' # Corresponding command for pkg_info
-PKGSYS_CMD_PKG_CREATE='pkg create'     # Corresponding command for pkg_create
 PKGSYS_CMD_PKG_DELETE='pkg delete'     # Corresponding command for pkg_delete
-PKGSYS_CMD_PKG_ADD='pkg add'   # Corresponding command for pkg_add
 PKGSYS_AVR_REFETCH_TIMES_PER_SITE=1    # Average number (integer) of retrials for retrieving package or distfiles per mirror site
 PKGSYS_AVR_REFETCH_TIMES_FOR_CHKSUMERR=2       #  Number (integer) of retrials for check sum error in retrieving a package
 
@@ -49,28 +46,29 @@ pkgsys_pkgchksum_file ()
 }
 
 # ============= Get the origin of the currently used pkg(8) =============
+# NOTE: Assumed to be unflavored.
 pkgsys_portsmgmt_pkg ()
 {
-       local origin
+       local origin_unflavored
        if [ ! -e "${DBDIR}/PKG_ORIGIN" ]
        then
-               origin=`pkgsys_sysvar PKG_ORIGIN` || :
-               [ -n "$origin" -a -d "${PORTSDIR}/$origin" ] || origin=ports-mgmt/pkg
-               echo "$origin" > ${DBDIR}/PKG_ORIGIN
+               origin_unflavored=`pkgsys_sysvar PKG_ORIGIN` || :
+               [ -n "$origin_unflavored" -a -d "${PORTSDIR}/$origin_unflavored" ] || origin_unflavored=ports-mgmt/pkg
+               echo "$origin_unflavored" > ${DBDIR}/PKG_ORIGIN
        fi
        cat "${DBDIR}/PKG_ORIGIN"
 }
 
 # ============= Get the origin of the currently used dialog4ports(1) =============
+# NOTE: Assumed to be unflavored.
 pkgsys_portsmgmt_dialog4ports ()
 {
-       echo "$origin"
-       local origin
+       local origin_unflavored
        if [ ! -e "${DBDIR}/DIALOGPORT" ]
        then
-               origin=`pkgsys_sysvar DIALOGPORT` || :
-               [ -n "$origin" -a -d "${PORTSDIR}/$origin" ] || origin=ports-mgmt/dialog4ports
-               echo "$origin" > ${DBDIR}/DIALOGPORT
+               origin_unflavored=`pkgsys_sysvar DIALOGPORT` || :
+               [ -n "$origin_unflavored" -a -d "${PORTSDIR}/$origin_unflavored" ] || origin_unflavored=ports-mgmt/dialog4ports
+               echo "$origin_unflavored" > ${DBDIR}/DIALOGPORT
        fi
        cat "${DBDIR}/DIALOGPORT"
 }
@@ -78,23 +76,36 @@ pkgsys_portsmgmt_dialog4ports ()
 # ============= Check whether a port is indispensable for the standard function of the ports/packages system =============
 pkgsys_is_pkgtool ()
 {
-       case $1 in
-       ports-mgmt/pkg|ports-mgmt/pkg-devel|ports-mgmt/dialog4ports)
+       local origin origin_unflavored
+       origin=$1
+       origin_unflavored=`echo "$origin" | sed 's/@.*$//'`
+       case $origin_unflavored in
+       ports-mgmt/pkg | ports-mgmt/pkg-devel | ports-mgmt/dialog4ports | ports-mgmt/dialog4ports-static )
+               ;;
+       *)      return 1
                ;;
-       *)      return 1;;
        esac
 }
 
 # ============= Check whether a port is indispensable for package operations =============
 pkgsys_is_necessary_pkgtool ()
 {
-       [ x"$WITH_PKGNG" = x'yes' -a \( x"$1" = x'ports-mgmt/pkg' -o x"$1" = x'ports-mgmt/pkg-devel' \) ]
+       local origin origin_unflavored
+       origin=$1
+       origin_unflavored=`echo "$origin" | sed 's/@.*$//'`
+       [ x"$WITH_PKGNG" = x'yes' -a \( x"$origin_unflavored" = x'ports-mgmt/pkg' -o x"$origin_unflavored" = x'ports-mgmt/pkg-devel' \) ]
 }
 
 # ============= Get the extended regular expression pattern of ports for pkg(8) =============
 pkgsys_pkgtools_ports_filter_regexp ()
 {
-       echo '^ports-mgmt/(pkg|pkg-devel)$'
+       echo '^ports-mgmt/(pkg|pkg-devel)(|@.*)$'
+}
+
+# ============= Get the extended regular expression pattern of package names for pkg(8) =============
+pkgsys_pkgtools_pkgs_filter_regexp ()
+{
+       echo '^(pkg|pkg-devel)-[0-9]\.'
 }
 
 # ============= Check whether the dialog for selecting port options is dialog4ports =============
@@ -199,7 +210,7 @@ pkgsys_fetch_legacy_remote ()
                return 1
        fi
        needs_fetch=yes
-       [ -d "${PKGREPOSITORY}" ] || mkdir -p "${PKGREPOSITORY}"
+       mkdir -p "${PKGREPOSITORY}"
        if [ -e "${PKGREPOSITORY}/$pkg.tbz" ]
        then
                if [ -e "${PKGREPOSITORY}/$pkg.md5=$validMD5.tbz" ]
@@ -247,14 +258,14 @@ pkgsys_fetch_legacy_remote__fetched_pkg ()
 }
 
 # ============= Check whether the dependency of a legacy package is the latest =============
-pkg_is_dependency_of_a_legacypkg_latest ()
+pkgsys_is_dependency_of_a_legacypkg_latest ()
 {
        local pkgarc tmp_extract tmp_contents tmp_origin tmp_pkg pkg nlines iline origin_req pkg_req pkg_new
        pkgarc=$1
-       tmp_extract=${TMPDIR}/pkgng:pkg_is_dependency_of_a_legacypkg_latest:extract
-       tmp_contents=${TMPDIR}/pkgng:pkg_is_dependency_of_a_legacypkg_latest:contents
-       tmp_origin=${TMPDIR}/pkgng:pkg_is_dependency_of_a_legacypkg_latest:origin
-       tmp_pkg=${TMPDIR}/pkgng:pkg_is_dependency_of_a_legacypkg_latest:pkg
+       tmp_extract=${TMPDIR}/pkgng:pkgsys_is_dependency_of_a_legacypkg_latest:extract
+       tmp_contents=${TMPDIR}/pkgng:pkgsys_is_dependency_of_a_legacypkg_latest:contents
+       tmp_origin=${TMPDIR}/pkgng:pkgsys_is_dependency_of_a_legacypkg_latest:origin
+       tmp_pkg=${TMPDIR}/pkgng:pkgsys_is_dependency_of_a_legacypkg_latest:pkg
        pkg=`pkgsys_pkgarc_to_pkgname "$pkgarc"`
        [ -e "$pkgarc" ] || return
        rm -rf "$tmp_extract"
@@ -292,7 +303,8 @@ pkgsys_def_pkgtools ()
        then
                PKGSYS_USE_PKGNG=`cat "${DBDIR}/WITH_PKGNG"`
        else
-               PKGSYS_USE_PKGNG=`pkgsys_sysvar WITH_PKGNG | tr '[:upper:]' '[:lower:]'`
+               PKGSYS_USE_PKGNG=`pkgsys_sysvar WITH_PKG | tr '[:upper:]' '[:lower:]'`
+               [ -n "$PKGSYS_USE_PKGNG" ] || PKGSYS_USE_PKGNG=`pkgsys_sysvar WITH_PKGNG | tr '[:upper:]' '[:lower:]'`
                if [ -d "${DBDIR}" ] && misc_is_superuser_privilege
                then
                        echo "$PKGSYS_USE_PKGNG" > ${DBDIR}/WITH_PKGNG.tmp
@@ -301,11 +313,9 @@ pkgsys_def_pkgtools ()
        fi
        if [ "x$PKGSYS_USE_PKGNG" = xyes ]
        then
+               export WITH_PKG=yes
                export WITH_PKGNG=yes
-               PKGSYS_CMD_PKG_INFO='pkg info'
-               PKGSYS_CMD_PKG_CREATE='pkg create'
                PKGSYS_CMD_PKG_DELETE='pkg delete'
-               PKGSYS_CMD_PKG_ADD='pkg add'
                pkg_is_tool_available ()
                {
                        if [ -x /usr/sbin/pkg ]
@@ -321,18 +331,18 @@ pkgsys_def_pkgtools ()
                {
                        pkg info -qa 2> /dev/null
                }
-               pkg_info_qoa ()
-               {
-                       pkg info -qoa 2> /dev/null
-               }
+#              pkg_info_qoa ()
+#              {
+#                      pkg info -qoa 2> /dev/null
+#              }
 #              pkg_info_qox ()
 #              {
 #                      pkg info -qox "$@" 2> /dev/null
 #              }
-               pkg_info_qoX ()
-               {
-                       pkg info -qox "$@" 2> /dev/null
-               }
+#              pkg_info_qoX ()
+#              {
+#                      pkg info -qox "$@" 2> /dev/null
+#              }
                pkg_info_qO ()
                {
                        pkg info -qO "$@" 2> /dev/null
@@ -351,7 +361,7 @@ pkgsys_def_pkgtools ()
                }
                pkg_info_eO ()
                {
-                       pkg info -eO "$1" 2> /dev/null
+                       pkg info -eO "$@" 2> /dev/null
                }
                pkg_info_Eg ()
                {
@@ -369,6 +379,29 @@ pkgsys_def_pkgtools ()
                {
                        pkg info -ql "$@" 2> /dev/null
                }
+               pkg_info_flavor ()
+               {
+                       local glob_unflavored
+                       glob_unflavored=$1
+                       pkg query -g '%At\t%Av' "$glob_unflavored" 2> /dev/null | grep -E '^flavor[[:space:]]' | cut -f 2
+               }
+               pkg_info_flavored_origin ()
+               {
+                       local glob_unflavored origin_unflavored
+                       glob_unflavored=$1
+                       origin_unflavored=`pkg_info_qo "$glob_unflavored" 2> /dev/null || :`
+                       flavor=`pkg_info_flavor "$glob_unflavored" 2> /dev/null || :`
+                       [ -z "$flavor" ] || flavor=@$flavor
+                       echo "$origin_unflavored$flavor"
+               }
+               pkg_info_all_flavored_origins ()
+               {
+                       local tmp_flavored tmp_flavored_ptn
+                       tmp_flavored_ptn=${TMPDIR}/pkg_info_all_flavored_origins:flavored_ptn
+                       pkg query '%o\t%At\t%Av' 2> /dev/null | grep -E '^[^[:space:]]+[[:space:]]flavor[[:space:]]' | cut -f 1,3 | tr '\t' @ | sed 's/@$//'
+                       pkg query '%n\t%At' 2> /dev/null | grep -E '^[^[:space:]]+[[:space:]]flavor$' | cut -f 1 > $tmp_flavored_ptn
+                       pkg query '%n\t%o' 2> /dev/null | grep -vFx -f "$tmp_flavored_ptn" | cut -f 2
+               }
                pkg_check_sanity ()
                {
                        local pkg tmp_stdout tmp_stderr
@@ -396,7 +429,12 @@ pkgsys_def_pkgtools ()
                }
                pkg_info_gen_pkg_origin_table ()
                {
-                       pkg query -g '%n-%v\t%o' \* 2> /dev/null > ${DBDIR}/installed_ports:pkg_vs_origin.tbl
+                       #       pkg query -g '%n-%v\t%o' \* 2> /dev/null > ${DBDIR}/installed_ports:pkg_vs_origin.tbl
+                       pkg info -qa | while read pkgname
+                       do
+                               origin=`pkg_info_flavored_origin "$pkgname"`
+                               printf '%s\t%s\n' "$pkgname" "$origin"
+                       done > ${DBDIR}/installed_ports:pkg_vs_origin.tbl
                }
                pkg_create_b ()
                {
@@ -417,12 +455,8 @@ pkgsys_def_pkgtools ()
                        rm -rf "$tmp_extract"
                        mkdir "$tmp_extract"
                        tar xf "$pkgarc" -C "$tmp_extract"
-                       prefix=`grep -m 1 '^prefix: ' "$tmp_extract/+MANIFEST" | sed 's/^prefix: *//'`
-                       prefix_parent=`dirname "$prefix"`
-                       cp -Rp "$tmp_extract/$prefix" "$prefix_parent"/
                        pkg=`pkgsys_pkgarc_to_pkgname "$pkgarc"`
-                       message_echo "INFO: Contents of $pkg are temporarily installed by simple copy."
-                       if env ASSUME_ALWAYS_YES=YES pkg add "$pkgarc"
+                       if env ASSUME_ALWAYS_YES=YES $tmp_extract/usr/local/sbin/pkg-static add "$pkgarc"
                        then
                                message_echo "INFO: $pkg is successfully registered."
                        else
@@ -446,73 +480,113 @@ pkgsys_def_pkgtools ()
                                fi
                        done
                        [ -n "$pkg_tool" ] && pkg_add_tools "$pkg_tool"
-                       [ -n "$pkg_gen" ] && env ASSUME_ALWAYS_YES=YES pkg add $pkg_gen
+                       if [ -n "$pkg_gen" ]
+                       then
+                               rm -rf "${TMPDIR}/pkg_add_f"
+                               mkdir -p "${TMPDIR}/pkg_add_f"
+                               ( cd "${TMPDIR}/pkg_add_f" && ln -s $pkg_gen && env ASSUME_ALWAYS_YES=YES pkg add * )
+                       fi
                }
                pkg_add_fF ()
                {
                        pkg_add_f "$@"
                }
+               pkg_inst_verify_pkg ()
+               {
+                       local pkg pkgarc
+                       pkg=$1
+                       pkgarc=`pkgsys_pkgname_to_pkgarc "${PKGNG_PKG_CACHEDIR}" "$pkg"` || return
+                       tar tf "$pkgarc" > /dev/null 2> /dev/null
+               }
                pkg_inst_remote_fetch ()
                {
-                       local pkg mode pkgarc
+                       local pkg
                        pkg=$1
-                       mode=$2
-                       tmp_extract=${TMPDIR}/pkgng:pkg_inst_remote:extract
-                       pkg fetch -yU "$pkg" || return
-                       pkgarc=`pkgsys_pkgname_to_pkgarc "${PKGNG_PKG_CACHEDIR}/All" "$pkg"` || return
-                       [ "x$mode" = xnodepschk ] && return
-                       rm -rf "$tmp_extract"
-                       mkdir "$tmp_extract"
-                       tar xf "$pkgarc" -C "$tmp_extract" +MANIFEST
-                       sed -E '1,/^deps:/d;/^[^[:space:]]/,$d;s/^[[:space:]]*([^:]+):[[:space:]]*\{origin:[[:space:]]*([^,]+),[[:space:]]*version:[[:space:]]*([^}]+)\}/\2\\\1-\3/' "$tmp_extract/+MANIFEST" \
-                               | tr '\\' '\t' | while read origin_req pkg_req
-                       do
-                               pkg_new=`cat "${DBDIR}/requires/$origin_req/new_version" 2> /dev/null` || :
-                               if [ -z "$pkg_new" -o "$pkg_new" != "$pkg_req" ]
-                               then
-                                       message_echo "WARNING: Requirements of remote package $pkg are not latest." >&2
-                                       return 1
-                               fi
-                       done
-                       :
+                       pkg fetch -yU "$pkg"
+               }
+               pkg_inst_remote_verify_fetch ()
+               {
+                       local pkg
+                       pkg=$1
+                       pkg_inst_verify_pkg "$pkg" && return
+                       pkg_inst_remote_fetch "$pkg" && pkg_inst_verify_pkg "$pkg"
                }
                pkg_inst_remote ()
                {
-                       local pkg mode pkgarc
+                       local pkg pkgarc
+                       pkg=$1
+                       pkg_inst_remote_verify_fetch "$pkg" || return
+                       pkgarc=`pkgsys_pkgname_to_pkgarc "${PKGNG_PKG_CACHEDIR}" "$pkg"` || return
+                       rm -rf "${TMPDIR}/pkg_inst_remote"
+                       mkdir -p "${TMPDIR}/pkg_inst_remote"
+                       ( cd "${TMPDIR}/pkg_inst_remote" && ln -s "$pkgarc" && env ASSUME_ALWAYS_YES=YES pkg add * )
+               }
+               pkg_inst_wild_verify_pkg ()
+               {
+                       local pkg pkgarc
                        pkg=$1
-                       mode=$2
-                       pkg_inst_remote_fetch "$pkg" "$mode" || return
-                       pkgarc=`pkgsys_pkgname_to_pkgarc "${PKGNG_PKG_CACHEDIR}/All" "$pkg"` || return
-                       env ASSUME_ALWAYS_YES=YES pkg add "$pkgarc"
+                       pkgarc=`pkgsys_pkgname_to_pkgarc "${PKGNG_PKG_CACHEDIR}" "$pkg"` || return
+                       pkgsys_is_dependency_of_a_legacypkg_latest "$pkgarc"
                }
                pkg_inst_remote_wild_fetch ()
                {
-                       local pkg mode pkgarc
+                       local pkg
                        pkg=$1
-                       mode=$2
                        if pkg_is_tool_available
                        then
-                               pkg_inst_remote "$pkg" "$mode" && return
+                               pkg_inst_remote "$pkg" && return
                        fi
                        pkgsys_is_legacy_tool_available || return
                        message_echo "INFO: Trying to use a legacy package and convert it to pkgng."
-                       pkgsys_fetch_legacy_remote "$pkg" || return
-                       pkgarc=`pkgsys_fetch_legacy_remote__fetched_pkg`
-                       [ "x$mode" = xnodepschk ] && return
-                       pkg_is_dependency_of_a_legacypkg_latest "$pkgarc"
+                       pkgsys_fetch_legacy_remote "$pkg"
+               }
+               pkg_inst_remote_wild_verify_fetch ()
+               {
+                       local pkg
+                       pkg=$1
+                       pkg_inst_wild_verify_pkg "$pkg" && return
+                       pkg_inst_remote_wild_fetch "$pkg" && pkg_inst_wild_verify_pkg "$pkg"
                }
                pkg_inst_remote_wild ()
                {
-                       local pkg mode pkgarc
+                       local pkg pkgarc
+                       pkg=$1
+                       if pkg_inst_remote_wild_verify_fetch "$pkg"
+                       then
+                               pkgarc=`pkgsys_fetch_legacy_remote__fetched_pkg`
+                               rm -rf "${TMPDIR}/pkg_inst_remote_wild"
+                               mkdir -p "${TMPDIR}/pkg_inst_remote_wild"
+                               ( cd "${TMPDIR}/pkg_inst_remote_wild" && ln -s "$pkgarc" && pkg_add -ifF * ) || return
+                               message_echo "INFO: Trying to convert the installed legacy package to pkgng."
+                               pkg2ng || :
+                               message_echo "INFO: Checking whether the conversion is successful."
+                               pkg info -e "$pkg"
+                       fi
+               }
+               pkg_inst_remote_repository_version ()
+               {
+                       local origin origin_unflavored pkg pkgarc tmp_pkgcell
+                       origin=$1
+                       origin_unflavored=`expr "$origin" : '\([^@]*\)'` || return
+                       [ -n "$origin_unflavored" ] || return
+                       pkg fetch -yU "$origin_unflavored" || return
+                       pkg=`pkg rquery -U %n-%v "$origin_unflavored"` || return
+                       [ -n "$pkg" ] || return
+                       pkgarc=`pkgsys_pkgname_to_pkgarc "${PKGNG_PKG_CACHEDIR}" "$pkg"` || return
+                       tmp_pkgcell=${TMPDIR}/pkg_inst_remote_any_version:pkgcell
+                       rm -rf "$tmp_pkgcell"
+                       mkdir -p "$tmp_pkgcell"
+                       ( cd "$tmp_pkgcell" && ln -s "$pkgarc" && env ASSUME_ALWAYS_YES=YES pkg add * )
+               }
+               pkg_get_pkgs_timestamps ()
+               {
+                       pkg query '%n-%v\tng-epoch:%t' "$@"
+               }
+               pkg_get_pkg_timestamp ()
+               {
+                       local pkg
                        pkg=$1
-                       mode=$2
-                       pkg_inst_remote_wild_fetch "$pkg" "$mode" || return
-                       pkgarc=`pkgsys_fetch_legacy_remote__fetched_pkg`
-                       pkg_add -ifF "$pkgarc" || return
-                       message_echo "INFO: Trying to convert the installed legacy package to pkgng."
-                       pkg2ng || :
-                       message_echo "INFO: Checking whether the conversion is successful."
-                       pkg info -e "$pkg"
+                       pkg query '%t' "$pkg"
                }
                pkg_loadconf ()
                {
@@ -541,34 +615,38 @@ pkgsys_def_pkgtools ()
                                var=`expr "$srcline" : '^[[:space:]]*\([A-Z0-9_]*\)[[:space:]]*:.*'` || :
                                val=`expr "$srcline" : '^[[:space:]]*[A-Z0-9_]*[[:space:]]*:[[:space:]]*\(.*\)'` || :
                                eval PKGNG_$var=\$val
-                               misc_get_all_vardefs | grep -E "^PKGNG_$var="
+                               misc_get_all_vardefs | grep "^PKGNG_$var="
                        done > ${TMPDIR}/pkgsys_def_pkgtools:pkg.conf.sh
                        . "${TMPDIR}/pkgsys_def_pkgtools:pkg.conf.sh"
                }
                pkg_rescue_tools ()
                {
-                       local packagepath checksumpath pkgname is_successful
-                       packagepath=`pkgsys_get_backup_pkg \`pkgsys_portsmgmt_pkg\`` && \
+                       local origin_portsmgmt packagepath checksumpath pkgname is_successful
+                       origin_portsmgmt=`pkgsys_portsmgmt_pkg`
+                       packagepath=`pkgsys_get_backup_pkg "$origin_portsmgmt"` && \
                                pkg_add_tools "$packagepath" && return
                        pkg_is_tool_available && return
-                       message_echo "WARNING: WITH_PKGNG is set, but pkgng is still missing. It is installed now." >&2
+                       message_echo "WARNING: WITH_PKG or WITH_PKGNG is set, but pkgng is still missing. It is installed now." >&2
                        pkgsys_ready_checksum_file || return
                        message_echo "INFO: Installing pkgng by legacy package tool."
                        checksumpath=`pkgsys_ready_checksum_file__fetched_file`
                        pkgname=`sed 's/^MD5[[:space:]]*(//;s/\.tbz)[[:space:]]*=[^=]*$//' "$checksumpath" \
-                               | grep -m 1 -E -e "^pkg-[0-9]"` || :
-                       [ -n "$pkgname" ] && pkg_inst_remote_wild "$pkgname" nodepschk && return
+                               | grep -m 1 '^pkg-[0-9]'` || :
+                       [ -n "$pkgname" ] && pkg_inst_remote_wild "$pkgname" && return
                        message_echo "INFO: Failed by package, so installing pkgng by port."
-                       grep -v '^[[:space:]]*WITH_PKGNG=' /etc/make.conf > ${TMPDIR}/make.conf
+                       grep -Ev '^[[:space:]]*WITH_PKG(|NG)=' /etc/make.conf > ${TMPDIR}/make.conf 2> /dev/null || :
+                       echo WITHOUT_PKG=yes >> ${TMPDIR}/make.conf
                        echo WITHOUT_PKGNG=yes >> ${TMPDIR}/make.conf
                        ( set -e
+                               unset WITH_PKG
                                unset WITH_PKGNG
+                               unset WITHOUT_PKG
                                unset WITHOUT_PKGNG
-                               
                                message_echo "INFO: Attempting deinstallation of pkg(8) to make sure."
-                               env __MAKE_CONF="${TMPDIR}/make.conf" make -C "${PORTSDIR}/`pkgsys_portsmgmt_pkg`" deinstall || :
+                               portsmgmt_port_path=`pkgsys_get_portpath_from_origin "$origin_portsmgmt"`
+                               env __MAKE_CONF="${TMPDIR}/make.conf" make -C "$portsmgmt_port_path" deinstall || :
                                message_echo "INFO: Attempting (re)installation by pkg(8)."
-                               env __MAKE_CONF="${TMPDIR}/make.conf" make -C "${PORTSDIR}/`pkgsys_portsmgmt_pkg`" reinstall clean
+                               env __MAKE_CONF="${TMPDIR}/make.conf" make -C "$portsmgmt_port_path" reinstall clean
                        ) && {
                                pkg2ng || :
                                pkg_is_tool_available
@@ -584,12 +662,10 @@ pkgsys_def_pkgtools ()
                message_echo "ERROR: Pkgng is disabled although the legacy packages tools are unavailable. Resolve the problem manually." >&2
                exit 1
        else
+               unset WITH_PKG
                unset WITH_PKGNG
                PKGSYS_USE_PKGNG=no
-               PKGSYS_CMD_PKG_INFO='pkg_info'
-               PKGSYS_CMD_PKG_CREATE='pkg_create'
                PKGSYS_CMD_PKG_DELETE='pkg_delete'
-               PKGSYS_CMD_PKG_ADD='pkg_add'
                pkg_is_tool_available ()
                {
                        pkgsys_is_legacy_tool_available
@@ -598,18 +674,18 @@ pkgsys_def_pkgtools ()
                {
                        pkg_info -Ea 2> /dev/null
                }
-               pkg_info_qoa ()
-               {
-                       pkg_info -qoa 2> /dev/null
-               }
+#              pkg_info_qoa ()
+#              {
+#                      pkg_info -qoa 2> /dev/null
+#              }
 #              pkg_info_qox ()
 #              {
 #                      pkg_info -qox "$@" 2> /dev/null
 #              }
-               pkg_info_qoX ()
-               {
-                       pkg_info -qoX "$@" 2> /dev/null
-               }
+#              pkg_info_qoX ()
+#              {
+#                      pkg_info -qoX "$@" 2> /dev/null
+#              }
                pkg_info_qO ()
                {
                        pkg_info -qO "$@" 2> /dev/null
@@ -620,7 +696,7 @@ pkgsys_def_pkgtools ()
                }
                pkg_info_qr ()
                {
-                       pkg_info -qr "$@" | grep '^@pkgdep ' | sed 's/^@pkgdep[[:space:]]*//' 2> /dev/null
+                       pkg_info -qr "$@" 2> /dev/null | sed -n 's/^@pkgdep[[:space:]]*//p'
                }
                pkg_info_e ()
                {
@@ -628,7 +704,7 @@ pkgsys_def_pkgtools ()
                }
                pkg_info_eO ()
                {
-                       [ `pkg_info -qO "$1" 2> /dev/null | wc -l` -gt 0 ]
+                       [ `pkg_info -qO "$@" 2> /dev/null | wc -l` -gt 0 ]
                }
                pkg_info_Eg ()
                {
@@ -636,7 +712,7 @@ pkgsys_def_pkgtools ()
                }
                pkg_info_qR ()
                {
-                       pkg_info -qR "$@" | grep -v '^$' 2> /dev/null
+                       pkg_info -qR "$@" 2> /dev/null | grep -v '^$'
                }
                pkg_info_Ex ()
                {
@@ -646,6 +722,21 @@ pkgsys_def_pkgtools ()
                {
                        pkg_info -qL "$@" 2> /dev/null
                }
+               pkg_info_flavor ()
+               {
+                       pkg_info -e "$@" 2> /dev/null && echo
+                       :
+               }
+               pkg_info_flavored_origin ()
+               {
+                       local glob_unflavored tmp_stdout
+                       glob_unflavored=$1
+                       pkg_info_qo "$glob_unflavored" 2> /dev/null
+               }
+               pkg_info_all_flavored_origins ()
+               {
+                       pkg_info_qoa 2> /dev/null
+               }
                pkg_check_sanity ()
                {
                        local pkg tmp_stdout tmp_stderr
@@ -653,8 +744,8 @@ pkgsys_def_pkgtools ()
                        tmp_stdout=${TMPDIR}/pkgng:pkg_check_sanity:stdout
                        tmp_stderr=${TMPDIR}/pkgng:pkg_check_sanity:stderr
                        pkg_info -qg "$pkg" > $tmp_stdout 2> $tmp_stderr || :
-                       grep ' fails the original MD5 checksum$' "$tmp_stdout" | sed 's/ fails the original MD5 checksum$//' || :
-                       grep "^pkg_info: .* doesn't exist$" "$tmp_stderr" | sed -E "s/^pkg_info: (.*) doesn't exist$/\1/" || :
+                       sed -n 's/ fails the original MD5 checksum$//p' "$tmp_stdout" 2> /dev/null || :
+                       sed -nE "s/^pkg_info: (.*) doesn't exist$/\1/p" "$tmp_stderr" 2> /dev/null || :
                }
                pkg_which ()
                {
@@ -680,61 +771,192 @@ pkgsys_def_pkgtools ()
                }
                pkg_add_f ()
                {
-                       pkg_add -if "$@"
+                       rm -rf "${TMPDIR}/pkg_add_f"
+                       mkdir -p "${TMPDIR}/pkg_add_f"
+                       ln -s "$@" "${TMPDIR}/pkg_add_f"
+                       ( cd "${TMPDIR}/pkg_add_f" && pkg_add -if * )
                }
                pkg_add_fF ()
                {
-                       pkg_add -ifF "$@"
+                       rm -rf "${TMPDIR}/pkg_add_f"
+                       mkdir -p "${TMPDIR}/pkg_add_f"
+                       ln -s "$@" "${TMPDIR}/pkg_add_f"
+                       ( cd "${TMPDIR}/pkg_add_f" && pkg_add -ifF * )
+               }
+               pkg_inst_verify_pkg ()
+               {
+                       local pkg pkgarc
+                       pkg=$1
+                       pkgarc=`pkgsys_fetch_legacy_remote__fetched_pkg` || return
+                       pkgsys_is_dependency_of_a_legacypkg_latest "$pkgarc"
                }
                pkg_inst_remote_fetch ()
                {
-                       local pkg mode pkgarc
+                       local pkg
+                       pkg=$1
+                       pkgsys_fetch_legacy_remote "$pkg"
+               }
+               pkg_inst_remote_verify_fetch ()
+               {
+                       local pkg
                        pkg=$1
-                       mode=$2
-                       pkgsys_fetch_legacy_remote "$pkg" || return
-                       pkgarc=`pkgsys_fetch_legacy_remote__fetched_pkg`
-                       [ "x$mode" = xnodepschk ] && return
-                       pkg_is_dependency_of_a_legacypkg_latest "$pkgarc"
+                       pkg_inst_verify_pkg "$pkg" && return
+                       pkg_inst_remote_fetch "$pkg" && pkg_inst_verify_pkg "$pkg"
                }
                pkg_inst_remote ()
                {
-                       local pkg mode pkgarc
+                       local pkg pkgarc
                        pkg=$1
-                       mode=$2
-                       pkg_inst_remote_fetch "$pkg" "$mode" || return
-                       pkgarc=`pkgsys_fetch_legacy_remote__fetched_pkg`
-                       pkg_add "$pkgarc" || return
+                       if pkg_inst_remote_verify_fetch "$pkg"
+                       then
+                               pkgarc=`pkgsys_fetch_legacy_remote__fetched_pkg`
+                               rm -rf "${TMPDIR}/pkg_inst_remote"
+                               mkdir -p "${TMPDIR}/pkg_inst_remote"
+                               ln -s "$@" "${TMPDIR}/pkg_add_f"
+                               ( cd "${TMPDIR}/pkg_inst_remote" && ls -s "$pkgarc" && pkg_add -ifF * )
+                       fi
+               }
+               pkg_inst_wild_verify_pkg ()
+               {
+                       pkg_inst_verify_pkg "$@"
                }
                pkg_inst_remote_wild_fetch ()
                {
-                       pkg_inst_remote_fetch "$1" "$2"
+                       pkg_inst_remote_fetch "$@"
+               }
+               pkg_inst_remote_wild_verify_fetch ()
+               {
+                       pkg_inst_remote_verify_fetch "$@"
                }
                pkg_inst_remote_wild ()
                {
-                       pkg_inst_remote "$1" "$2"
+                       pkg_inst_remote "$@"
+               }
+               pkg_inst_remote_repository_version ()
+               {
+                       local origin checksumpath version_regexp pkgbase_regexp
+                       origin=$1
+                       pkgsys_ready_checksum_file || return
+                       checksumpath=`pkgsys_ready_checksum_file__fetched_file`
+                       version_regexp=`database_build_make "$origin" -V PORTVERSION | str_escape_regexp_filter`
+                       pkgbase_regexp=`database_build_get_new_pkgname "$origin" | sed -E "s/$version_regexp$//" | str_escape_regexp_filter`
+                       sed -nE "s/^MD5[[:space:]]*\(($pkgbase_regexp.*)\.tbz\)[[:space:]]*=.*/\1/p" "$checksumpath" | while read pkg
+                       do
+                               pkg_inst_remote "$pkg" && return
+                       done
+               }
+               pkg_get_pkgs_timestamps ()
+               {
+                       ls -lD legacy:%s ${PKG_DBDIR} | \
+                               sed -E 's/[[:space:]]+/ /g' | cut -w -f 6,7 | grep -v '^$' | \
+                               sed -E 's/^([^[:space:]]*)[[:space:]]*([^[:space:]]*)/\2 \1/' | tr ' ' '\t'
+               }
+               pkg_get_pkg_timestamp ()
+               {
+                       local pkg portdb
+                       pkg=$1
+                       portdb=`echo "$pkg" | sed 's/-[0-9].*//'`
+                       ls -lD legacy:%s "${PKG_DBDIR}/$portdb" | \
+                               sed -E 's/[[:space:]]+/ /g' | cut -w -f 6 | grep -v '^$' 
                }
                pkg_loadconf () { :; }
                pkg_rescue_tools () { :; }
        fi
 }
 
-# ============= Check existence of initially or currently installed package for an origin =============
-pkgsys_pkg_info_eO ()
+# ============= Get the unflavored part of a flavored origin =============
+pkgsys_get_unflavored_origin ()
 {
-       local origin origin_regexp
+       local origin origin_unflavored
+       origin=$1
+       origin_unflavored=`echo "$origin" | sed 's/@.*$//'`
+       echo "$origin_unflavored"
+}
+
+# ============= Get the port path from a flavored origin =============
+pkgsys_get_portpath_from_origin ()
+{
+       local origin origin_unflavored
+       origin=$1
+       origin_unflavored=`pkgsys_get_unflavored_origin "$origin"`
+       echo "${PORTSDIR}/$origin_unflavored"
+}
+
+# ============= Get the flavor from a flavored origin =============
+pkgsys_get_flavor_from_origin ()
+{
+       local origin flavor
+       origin=$1
+       flavor=`echo "$origin" | sed -E 's/^[^@]*@?//'`
+       echo "$flavor"
+}
+
+# ============= Compose a flavored origin name =============
+pkgsys_compose_flavored_origin ()
+{
+       local origin flavor
+       origin=$1
+       flavor=$2
+       origin_unflavored=`pkgsys_get_unflavored_origin "$origin"`
+       [ -z "$flavor" ] || flavor=@$flavor
+       echo "$origin_unflavored$flavor"
+}
+
+# ============= Check existence of a port for a flavored origin =============
+pkgsys_exists_port ()
+{
+       local origin port_path
+       origin=$1
+       port_path=`pkgsys_get_portpath_from_origin "$origin"`
+       [ -d "$port_path" ]
+}
+
+# ============= Get the installed package name from a flavored origin =============
+pkgsys_get_installed_pkg_from_origin ()
+{
+       local origin origin_unflavored flavor_origin flavor_pkg
+       origin=$1
+       origin_unflavored=`pkgsys_get_unflavored_origin "$origin"`
+       flavor_origin=`pkgsys_get_flavor_from_origin "$origin"`
+       pkg_info_qO "$origin_unflavored" 2> /dev/null | while read pkgname
+       do
+               flavor_pkg=`pkg_info_flavor "$pkgname"`
+               if [ "x$flavor_origin" = "x$flavor_pkg" ]
+               then
+                       echo "$pkgname"
+                       break
+               fi
+       done
+       :
+}
+
+# ============= Check existence of an installed package for a flavored origin =============
+pkgsys_exists_from_orig ()
+{
+       local origin origin_unflavored flavor_origin flavor_pkg
+       origin=$1
+       origin_unflavored=`pkgsys_get_unflavored_origin "$origin"`
+       pkg_info_eO "$origin_unflavored" 2> /dev/null || return
+       flavor_origin=`pkgsys_get_flavor_from_origin "$origin"`
+       flavor_pkg=`pkg_info_flavor "$origin_unflavored"`
+       [ "x$flavor_origin" = "x$flavor_pkg" ]
+}
+
+# ============= Check existence of initially or currently installed package for a flavored origin =============
+pkgsys_exists_or_existed_from_orig ()
+{
+       local origin
        origin=$1
-       origin_regexp=`str_escape_regexp "$origin"`
        cut -f 2 "${DBDIR}/installed_ports:pkg_vs_origin.tbl" 2> /dev/null \
-               | grep -q -E "^$origin_regexp$" && return
-       pkg_info_eO "$origin"
+               | grep -q -Fx "$origin" || pkgsys_exists_from_orig "$origin"
 }
 
-# ============= Get the name of an initially installed package for an origin =============
-pkgsys_pkg_info_qO_init ()
+# ============= Get the name of an initially installed package for a flavored origin =============
+pkgsys_get_init_pkg_from_orig ()
 {
-       local origin tmppkg origin_regexp npkgs
+       local origin tmppkg origin_regexp npkgs origin_unflavored flavor_origin flavor_pkg
        origin=$1
-       tmppkg=${TMPDIR}/pkgsys_pkg_info_qO_init::pkg
+       tmppkg=${TMPDIR}/pkgsys_get_init_pkg_from_orig::pkg
        origin_regexp=`str_escape_regexp "$origin"`
        sed -n -E "/[[:space:]]$origin_regexp$/p" "${DBDIR}/installed_ports:pkg_vs_origin.tbl" 2> /dev/null \
                | cut -f 1 > $tmppkg || :
@@ -743,8 +965,19 @@ pkgsys_pkg_info_qO_init ()
        then
                cat "$tmppkg"
        else
-               pkg_info_qO "$origin"
+               origin_unflavored=`pkgsys_get_unflavored_origin "$origin"`
+               flavor_origin=`pkgsys_get_flavor_from_origin "$origin"`
+               pkg_info_qO "$origin_unflavored" 2> /dev/null | while read pkgname
+               do
+                       flavor_pkg=`pkg_info_flavor "$pkgname"`
+                       if [ "x$flavor_origin" = "x$flavor_pkg" ]
+                       then
+                               echo "$pkgname"
+                               break
+                       fi
+               done
        fi
+       :
 }
 
 # ============= Get the package name of this utility =============
@@ -753,18 +986,21 @@ pkgsys_get_my_current_pkg ()
        pkg_info_Ex "${APPNAME}-[0-9].*"
 }
 
-# ============= Get the origin of this utility =============
+# ============= Get the flavored origin of this utility =============
 pkgsys_get_my_origin ()
 {
-       pkg_info_qo "`pkgsys_get_my_current_pkg`"
+       pkgsys_get_my_current_pkg | while read pkgname
+       do
+               pkg_info_flavored_origin "$pkgname"
+       done
 }
 
-# ============= Get the origin of an initially installed package by ambiguous matching =============
+# ============= Get the flavored origin of an initially installed package by ambiguous matching =============
 pkgsys_init_pkg_orig_by_ambiguous_matching ()
 {
        local pkg origin tmporigin ambsuffix len_pkg pkg_regexp norigins
        pkg=$1
-       origin=`pkg_info_qo "$pkg" || :`
+       origin=`pkg_info_flavored_origin "$pkg"`
        [ -n "$origin" ] && { echo "$origin"; return; }
        tmporigin=${TMPDIR}/pkgsys_init_pkg_orig_by_ambiguous_matching::origin
        ambsuffix=
@@ -806,12 +1042,14 @@ pkgsys_show_pkg_updating_commands ()
        fi
 }
 
-# ============= Evaluation of ports globs =============
+# ============= Evaluation of flavored ports globs =============
 pkgsys_eval_ports_glob ()
 {
-       local pkglist origlist
+       local pkglist unflavored_origlist tmp_flavors
        pkglist=${DBDIR}/pkgsys_eval_ports_glob:pkg.lst
-       origlist=${DBDIR}/pkgsys_eval_ports_glob:origin.lst
+       unflavored_origlist=${DBDIR}/pkgsys_eval_ports_glob:origin_unflavored.lst
+       tmp_flavors=${TMPDIR}/pkgsys_eval_ports_glob:flavors
+       # Test the access privilege as the superuser or not
        if [ ! -r "$pkglist" ]
        then
                if touch "$pkglist" 2>/dev/null
@@ -821,20 +1059,22 @@ pkgsys_eval_ports_glob ()
                        pkglist=${TMPDIR}/pkgsys_eval_ports_glob:pkg.lst
                fi
        fi
-       if [ ! -r "$origlist" ]
+       if [ ! -r "$unflavored_origlist" ]
        then
-               if touch "$origlist" 2>/dev/null
+               if touch "$unflavored_origlist" 2>/dev/null
                then
-                       rm "$origlist"
+                       rm "$unflavored_origlist"
                else
-                       origlist=${TMPDIR}/pkgsys_eval_ports_glob:origin.lst
+                       unflavored_origlist=${TMPDIR}/pkgsys_eval_ports_glob:origin.lst
                fi
        fi
+       # Preparation of customized databases
        [ -f "$pkglist" ] \
                || cut -d \| -f 1 "${PORTS_INDEX_DB}" > $pkglist
-       [ -f "$origlist" ] \
+       [ -f "$unflavored_origlist" ] \
                || cut -d \| -f 2 "${PORTS_INDEX_DB}" \
-               | sed -E "s/^`str_escape_regexp "${PORTSDIR}"`\///" > $origlist
+               | sed -E "s/^`str_escape_regexp "${PORTSDIR}"`\///" > $unflavored_origlist
+       # Evaluation
        while [ $# -gt 0 ]
        do
                glob=$1
@@ -843,28 +1083,82 @@ pkgsys_eval_ports_glob ()
                glob_regexp=`str_convert_portsglob_to_regexp_pattern "$glob"`
                if expr "$glob" : '.*/' > /dev/null 2>&1
                then
-                       grep -E "$glob_regexp" "$origlist" 2>&1 || :
+                       if expr "$glob" : '.*@' > /dev/null 2>&1
+                       then
+                               glob_regexp_unflavored=`expr "$glob_regexp" : '\([^@]*\)' || :`$
+                               glob_regexp_flavor=^`expr "$glob_regexp" : '[^@]*@\([^@]*\)' || :`
+                                       
+                               grep -E "$glob_regexp_unflavored" "$unflavored_origlist" 2>&1 | while read origin_unflavored
+                               do
+                                       make -C "${PORTSDIR}/$origin_unflavored" -V FLAVORS 2> /dev/null | \
+                                               tr '[:space:]' '\n' | grep -v '^$' | grep -E "$glob_regexp_flavor" | sed -E "s|^|$origin_unflavored@|"
+                               done
+                               {
+                                       pkg_info_all_flavored_origins
+                                       cut -f 2 "${DBDIR}/installed_ports:pkg_vs_origin.tbl" 2> /dev/null
+                               } | grep -E "$glob_regexp" 2>&1 || :
+                       else
+                               grep -E "$glob_regexp" "$unflavored_origlist" 2>&1 | while read origin_unflavored
+                               do
+                                       origin_unflavored_rpl=`str_escape_replaceval "$origin_unflavored"`
+                                       make -C "${PORTSDIR}/$origin_unflavored" -V FLAVORS 2> /dev/null | \
+                                               tr '[:space:]' '\n' | grep -v '^$' > $tmp_flavors || :
+                                       if [ `wc -l < $tmp_flavors` -gt 0 ]
+                                       then
+                                               sed -E "s|^|$origin_unflavored_rpl@|" "$tmp_flavors"
+                                       else
+                                               echo "$origin_unflavored"
+                                       fi
+                               done
+                       fi
+                       glob_regexp_allflavors=`echo "$glob_regexp" | sed 's/$$/(|@.*)$/'`
                        {
-                               pkg_info_qoa
+                               pkg_info_all_flavored_origins
                                cut -f 2 "${DBDIR}/installed_ports:pkg_vs_origin.tbl" 2> /dev/null
-                       } | grep -E "$glob_regexp" 2>&1 || :
+                       } | grep -E "$glob_regexp_allflavors" 2>&1 || :
                else
                        if expr "$glob" : '^[a-z][a-zA-Z0-9_.+-]*[a-zA-Z0-9_.+]$' > /dev/null 2>&1 && \
                                [ `expr "$glob" : '.*-[0-9]' 2>&1` -eq 0 ]
                        then
-                               glob_regexp2=`expr "$glob_regexp" : '\(.*\)\$$' 2>&1`'-[0-9]'
+                               glob_regexp2=`expr "$glob_regexp" : '\(.*\)\$$' 2>&1 || :`'-[0-9]'
                        else
                                glob_regexp2=$glob_regexp
                        fi
                        grep -n -E "$glob_regexp2" "$pkglist" 2>&1 | cut -d : -f 1 \
                                | while read index
                        do
-                               sed -n ${index}p "$origlist"
+                               sed -n ${index}p "$unflavored_origlist"
+                       done | while read origin_unflavored
+                       do
+                               origin_unflavored_rpl=`str_escape_replaceval "$origin_unflavored"`
+                               make -C "${PORTSDIR}/$origin_unflavored" -V FLAVORS 2> /dev/null | \
+                                       tr '[:space:]' '\n' | grep -v '^$' > $tmp_flavors || :
+                               [ `wc -l < $tmp_flavors` -gt 0 ] || echo > $tmp_flavors
+                               sed -E "s/^/$origin_unflavored_rpl /" "$tmp_flavors"
+                       done | while read origin_unflavored flavor
+                       do
+                               if [ -n "$flavor" ]
+                               then
+                                       if make -C "${PORTSDIR}/$origin_unflavored" package-name FLAVOR=$flavor 2> /dev/null | \
+                                       grep -qE "$glob_regexp2"
+                                       then
+                                               echo "$origin_unflavored@$flavor"
+                                       fi
+                               else
+                                       if make -C "${PORTSDIR}/$origin_unflavored" package-name 2> /dev/null | \
+                                       grep -qE "$glob_regexp2"
+                                       then
+                                               echo "$origin_unflavored"
+                                       fi
+                               fi
                        done || :
-                       glob_regexp2=`expr "$glob_regexp" : '\(.*\)\$$' 2>&1`'[[:space:]]'
+                       glob_regexp2=`expr "$glob_regexp" : '\(.*\)\$$' 2>&1 || :`'[[:space:]]'
                        sed -n -E "/$glob_regexp2/p" "${DBDIR}/installed_ports:pkg_vs_origin.tbl" 2> /dev/null \
                                | cut -f 2 || :
-                       pkg_info_qoX "$glob_regexp" || :
+                       pkg_info_Ex "$glob_regexp" | while read pkgname
+                       do
+                               pkg_info_flavored_origin "$pkgname"
+                       done
                fi
        done | sort -u
 }
@@ -872,14 +1166,15 @@ pkgsys_eval_ports_glob ()
 # ============= Create a back-up package archive =============
 pkgsys_create_backup_pkg ()
 {
-       local pkgname dstdir origin backup_pkg_old pkgname_ptn backup_pkg dbpath pkgpath origin_regexp
+       local pkgname dstdir origin backup_pkg_old pkgname_ptn backup_pkg dbpath pkgpath
        pkgname=$1
        dstdir=$2
        rm -rf "${TMPDIR}"/package.tmp
        mkdir "${TMPDIR}"/package.tmp
-       origin=`pkg_info_qo "$pkgname"`
-       if backup_pkg_old=`pkgsys_get_backup_pkg "$origin"` \
-               [ "$backup_pkg_old" -nt "${DBDIR}/requires/$origin/installed_timestamp" ]
+       origin=`pkg_info_flavored_origin "$pkgname"`
+       if backup_pkg_old=`pkgsys_get_backup_pkg "$origin"` && \
+               [ ! -e "${DBDIR}/requires/$origin/installed_timestamp" -o \
+                       "$backup_pkg_old" -nt "${DBDIR}/requires/$origin/installed_timestamp" ]
        then
                echo "$backup_pkg_old"
                return
@@ -896,12 +1191,11 @@ pkgsys_create_backup_pkg ()
                return 1
        fi
        dbpath=${DBDIR}/backup/$origin
-       [ -d "$dbpath" ] || mkdir -p "$dbpath"
-       pkg_info_qL > $dbpath/previously_installed_files
-       [ -d "$dstdir" ] || mkdir -p "$dstdir"
+       mkdir -p "$dbpath"
+       pkg_info_qL "$pkgname" > $dbpath/previously_installed_files
+       mkdir -p "$dstdir"
        mv "${TMPDIR}/package.tmp/$backup_pkg" "$dstdir"
        pkgpath=$dstdir/$backup_pkg
-       origin_regexp=`str_escape_regexp "$origin"`
        cat "${DBDIR}/backup_pkgarcs.lst" 2> /dev/null | \
                while read origin_cur pkgpath_cur
                do
@@ -918,7 +1212,7 @@ pkgsys_create_backup_pkg ()
        echo "$pkgpath"
 }
 
-# ============= Delete a back-up package archive for a port origin =============
+# ============= Delete a back-up package archive for a flavored port origin =============
 pkgsys_delete_backup_pkg ()
 {
        local origin origin_regexp
@@ -934,7 +1228,7 @@ pkgsys_delete_backup_pkg ()
        mv "${DBDIR}/backup_pkgarcs.lst.tmp" "${DBDIR}/backup_pkgarcs.lst"
 }
 
-# ============= Get an existing package archive path for a port origin =============
+# ============= Get an existing package archive path for a flavored port origin =============
 pkgsys_get_backup_pkg ()
 {
        local origin tmpnewest origin_regexp
@@ -953,7 +1247,7 @@ pkgsys_get_backup_pkg ()
        cat "$tmpnewest" 2> /dev/null
 }
 
-# ============= Get a file list to be restored by the current backup package for a port origin =============
+# ============= Get a file list to be restored by the current backup package for a flavored port origin =============
 pkgsys_get_restored_files_by_backup_pkg ()
 {
        local origin
@@ -961,17 +1255,14 @@ pkgsys_get_restored_files_by_backup_pkg ()
        cat "${DBDIR}/backup/$origin/previously_installed_files" 2> /dev/null || :
 }
 
-# ============= Check whether any file match restored files by the current backup package for a port origin =============
+# ============= Check whether any file match restored files by the current backup package for a flavored port origin =============
 pkgsys_chk_match_to_restored_files_by_backup_pkg ()
 {
-       local origin
+       local origin filelist dbfile
        origin=$1
-       pattern_file=$2
-       while read pattern
-       do 
-               grep -qE "$pattern" "${DBDIR}/backup/$origin/previously_installed_files" && return
-       done < $pattern_file
-       false
+       filelist=$2
+       dbfile=${DBDIR}/backup/$origin/previously_installed_files
+       grep -qFx -f "$filelist" "$dbfile" 2> /dev/null
 }
 
 # ============= Get a package name from a package archive file name =============
@@ -1002,14 +1293,14 @@ pkgsys_pkgname_to_pkgarc ()
        echo "$pkgdir/$pkgnode"
 }
 
-# ============= Get port origins matching a glob pattern even if nonexistent =============
+# ============= Get flavored port origins matching a glob pattern even if nonexistent =============
 pkgsys_eval_ports_glob_even_if_nonexistent ()
 {
        local glob_pattern
        glob_pattern=$1
        {
                pkgsys_eval_ports_glob "$glob_pattern" 2> /dev/null || :
-               echo "$glob_pattern" | grep '^[a-z][a-z]*/[a-zA-Z0-9_.+-][a-zA-Z0-9_.+-]*$' || :
+               echo "$glob_pattern" | grep -E '^[a-z]+/[a-zA-Z0-9_.+-]+(|@[a-zA-Z0-9_.+-]+)$' || :
        } | grep -v -e '^$' | sort -u
 }
 
@@ -1023,7 +1314,7 @@ pkgsys_register_evaluated_globs ()
        dirpath=`dirname "$listpath"`
        tmp_evaluated=${TMPDIR}/pkgsys_register_evaluated_globs:pkgsys_eval_ports_glob
        echo "$@" | sed -E 's/[ :]+/\
-/g' | grep -v '^$' | sort -u | while read glob
+/g' | grep -v '^$' | sort -u | while read -r glob
        do
                pkgsys_eval_ports_glob "$glob" > $tmp_evaluated
                [ `wc -l < $tmp_evaluated` -ge 1 ] || \
@@ -1034,10 +1325,12 @@ pkgsys_register_evaluated_globs ()
                cat "$tmp_evaluated"
        done | while read origin
        do
-               [ -d "$dirpath" ] || mkdir -p "$dirpath"
+               mkdir -p "$dirpath"
                case $mode in
-               remove) fileedit_rm_a_line "$origin" "$listpath";;
-               add)    fileedit_add_a_line_if_new "$origin" "$listpath";;
+               remove )        fileedit_rm_a_line "$origin" "$listpath"
+                       ;;
+               add )   fileedit_add_a_line_if_new "$origin" "$listpath"
+                       ;;
                esac
        done
 }
@@ -1052,7 +1345,7 @@ pkgsys_eval_installed_pkgs_globs ()
        [ -e "$tmp_evaluated" ] || return 0
        while read origin
        do
-               pkgsys_pkg_info_eO "$origin" || echo "$origin"
+               pkgsys_exists_or_existed_from_orig "$origin" || echo "$origin"
        done < $tmp_evaluated
 }
 
@@ -1064,10 +1357,10 @@ pkgsys_get_conflicting_pkgs_patterns ()
        origin=$2
        conflicts=`database_query_get_makevar_val "$origin" CONFLICTS`
        case $mode in
-       build)
+       build )
                conflicts=$conflicts' '`database_query_get_makevar_val "$origin" CONFLICTS_BUILD`
                ;;
-       install)
+       install )
                conflicts=$conflicts' '`database_query_get_makevar_val "$origin" CONFLICTS_INSTALL`
                ;;
        esac
@@ -1143,7 +1436,7 @@ pkgsys_sanitychk_pkgcontents ()
                fi
        done
        eval "$var_is_reinstall_encouraged=\$_is_reinstall_encouraged"
-       origin=`pkg_info_qo "$pkg"`
+       origin=`pkg_info_flavored_origin "$pkg"`
        if [ $opt_batch_mode = no ]
        then
                message_echo "[$pkg ($origin)]"
@@ -1156,3 +1449,101 @@ pkgsys_sanitychk_pkgcontents ()
        fi
        return 1
 }
+
+# ============= Check whether the port options database is once saved =============
+pkgsys_exists_saved_port_oprions_timestamps ()
+{
+       [ -d "${DBDIR}/ls_dbdir" ]
+}
+
+# ============= Get the current all timestamp information of port options =============
+pkgsys_get_current_port_oprions_timestamp ()
+{
+       local portdb_needle_regexp
+       portdb_needle_regexp=`str_escape_regexp "$1"`
+       {
+               ls -lD %Y%m%d:%H%M%S "${PORT_DBDIR}" | if [ -n "$portdb_needle_regexp" ]
+               then
+                       grep -E "[[:space:]]$portdb_needle_regexp$" || :
+               else
+                       cat
+               fi
+       } 2> /dev/null | cut -w -f 6,7 | while read datetime portdb
+       do
+               [ -d "${PORT_DBDIR}/$portdb" ] || continue
+               if [ -e "${PORT_DBDIR}/$portdb/options" ]
+               then
+                       datetime=`ls -lD %Y%m%d:%H%M%S "${PORT_DBDIR}/$portdb/options" 2> /dev/null | cut -w -f 6`
+               fi
+               printf '%s\t%s\n' "$portdb" "$datetime"
+       done
+}
+
+# ============= Get the saved all timestamp information of port options =============
+pkgsys_get_saved_port_oprions_timestamps_all ()
+{
+       cat "${DBDIR}/ls_dbdir/"*.log > $tmp_ls.db 2> /dev/null || :
+}
+
+# ============= Convert a list of port origins to port options timestamp log names =============
+pkgsys_conv_portorigin_to_port_oprion_timestamp_logname ()
+{
+       sed 's|/|_|'
+}
+
+# ============= Save the timestamp information of port options of a port =============
+pkgsys_save_port_oprion_timestamp ()
+{
+       local origin portoptlog portoptdb
+       origin=$1
+       portoptlog=`echo "$origin" | pkgsys_conv_portorigin_to_port_oprion_timestamp_logname`
+       if pkgsys_is_dialog4ports_used
+       then
+               portoptdb=`echo "$portoptlog" | sed 's/@.*//'`
+       else
+               portoptdb=`database_build_make "$origin" -V UNIQUENAME`
+       fi
+       mkdir -p "${DBDIR}/ls_dbdir"
+       pkgsys_get_current_port_oprions_timestamp "$portoptdb" > ${DBDIR}/ls_dbdir/$portoptlog.log 2> /dev/null || :
+}
+
+# ============= Get changed port options from the saved point =============
+pkgsys_get_changed_port_oprions ()
+{
+       local saved_log current_log tmp_log
+       saved_log=$1
+       current_log=$2
+       tmp_log=${TMPDIR}/pkgsys_get_changed_port_oprions.log
+       {
+               grep -vxF -f "$current_log" "$saved_log" || :
+               grep -vxF -f "$saved_log" "$current_log" || :
+       } | cut -w -f 1 | grep -v '^$' | sort -u > $tmp_log
+       if pkgsys_is_dialog4ports_used
+       then
+               grep '_' "$tmp_log" || :
+       else
+               cat "$tmp_log"
+       fi
+}
+
+# ============= Convert a list of port origins to port options database names =============
+pkgsys_conv_portorigins_to_portoptiondbs ()
+{
+       if pkgsys_is_dialog4ports_used
+       then
+               sed 's|_|/|'
+       else
+               cat "$tmp_ls.diff"
+       fi
+}
+       
+# ============= Register nonexistent port options databases =============
+pkgsys_register_list_nonexistent_portopriondb ()
+{
+       local dbpath
+       dbpath=${DBDIR}/ls_dbdir/%NONEXISTENT%.log
+       cat > $dbpath.new
+       touch  "$dbpath"
+       sort -u "$dbpath.new" "$dbpath" > $dbpath.tmp
+       mv "$dbpath.tmp" "$dbpath"
+}
index c089bce..e24d601 100644 (file)
@@ -2,7 +2,7 @@
 # ==============================================================================
 # portsreinstall library script
 # - Program control -
-# Copyright (C) 2013-2017 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# Copyright (C) 2013-2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
 # This software is distributed under the 2-Clause BSD License.
 # ==============================================================================
 
@@ -36,7 +36,7 @@ program_register_stage_complete ()
        local stagetag
        stagetag=$1
        rm -f "${DBDIR}/stage.reinit_loop/$stagetag"
-       [ -d "${DBDIR}/stage.complete" ] || mkdir -p "${DBDIR}/stage.complete"
+       mkdir -p "${DBDIR}/stage.complete"
        touch "${DBDIR}/stage.complete/$stagetag"
 }
 
@@ -45,7 +45,7 @@ program_reset_loop_for_stage ()
 {
        local stagetag
        stagetag=$1
-       [ -d "${DBDIR}/stage.reinit_loop" ] || mkdir -p "${DBDIR}/stage.reinit_loop"
+       mkdir -p "${DBDIR}/stage.reinit_loop"
        touch "${DBDIR}/stage.reinit_loop/$stagetag"
 }
 
@@ -64,7 +64,7 @@ program_register_stage_depends ()
        local stagetag prefix_rpl
        stagetag=$1
        shift
-       [ -d "${DBDIR}/stage.depends" ] || mkdir -p "${DBDIR}/stage.depends"
+       mkdir -p "${DBDIR}/stage.depends"
        prefix_rpl=`str_escape_replaceval "${DBDIR}/stage.depends/"`
        while [ $# -gt 0 ]
        do
@@ -165,7 +165,7 @@ program_exec_restartable_loop_operation ()
                iline=$(($iline+1))
                PROGRAM_STEP_PROGRESS=$(($PROGRAM_STEP_PROGRESS+1))
                PROGRAM_STEP_COUNTER="[$PROGRAM_STEP_PROGRESS/$PROGRAM_NUM_STEPS $(($PROGRAM_STEP_PROGRESS*100/$PROGRAM_NUM_STEPS))%]"
-               grep -q -E "^`str_escape_regexp \"$item\"`$" "$looplist.remain" 2> /dev/null || continue
+               grep -q -Fx "$item" "$looplist.remain" 2> /dev/null || continue
                _program_exec_restartable_loop_operation__routine "$item"
                fileedit_rm_a_line "$item" "$looplist.remain"
        done
index ddf63dd..df4ec2c 100644 (file)
@@ -2,17 +2,16 @@
 # ==============================================================================
 # portsreinstall library script
 # - Reinstallation processes -
-# Copyright (C) 2013-2017 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# Copyright (C) 2013-2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
 # This software is distributed under the 2-Clause BSD License.
 # ==============================================================================
 
 # ============= Variables =============
 # The following variables are available only within reinstall_exec and functions invoked by it.
 REINSTALL_PKGTAG=      # Tag indicating version changes by reinstallation of the current port
-REINSTALL_ORIGPKGTAG=  # Tag indicating the port origin and version changes by reinstallation of the current port
+REINSTALL_ORIGPKGTAG=  # Tag indicating the flavored port origin and version changes by reinstallation of the current port
 REINSTALL_CURRENTPKG=  # Currently installed package name of the current port
-REINSTALL_ORIGIN=      # Port origin of the current port
-REINSTALL_ORIGIN_REGEXP=       # Port origin of the current port where control characters of extended regular expression are escaped
+REINSTALL_ORIGIN=      # Flavored port origin of the current port
 REINSTALL_DBNODE_DIR=  # Path of the "requires" section of the temporary database for the current port
 REINSTALL_IS_CURRENTPKG_LATEST=        # Currently installed package name of the current port
 REINSTALL_DBSUFFIX=    # Database suffix for the evaluation method of dependencies
@@ -28,16 +27,16 @@ reinstall_skip ()
        fileedit_rm_a_line "$REINSTALL_ORIGIN" "${DBDIR}/stage.loop_list/reinst_todo.remain"
 }
 
-# ============= Check whether a package is forbidden due to conflicts =============
+# ============= Check whether a package is forbidden due to conflict =============
 reinstall_quick_chk_forbidden_conflicts ()
 {
        local pkg pkg_regexp_esc
        pkg=$1
        pkg_regexp_esc=`str_escape_regexp "$pkg"`
-       grep -qE "^$pkg_regexp_esc:" "${DBDIR}/forbidden_conflicts"
+       grep -qE "^$pkg_regexp_esc:" "${DBDIR}/forbidden_conflicts" 2> /dev/null
 }
 
-# ============= Check whether a package is forbidden due to conflicts =============
+# ============= Check whether a package is forbidden due to conflict =============
 reinstall_chk_forbidden_conflicts ()
 {
        local pkg tmp_forbidden pkg_regexp_esc
@@ -45,36 +44,62 @@ reinstall_chk_forbidden_conflicts ()
        tmp_forbidden=${TMPDIR}/reinstall_chk_forbidden_conflicts:forbidden
        pkg_regexp_esc=`str_escape_regexp "$pkg"`
        grep -E "^$pkg_regexp_esc:" "${DBDIR}/forbidden_conflicts" > $tmp_forbidden 2> /dev/null || return
-       pkg_info_e `cut -d : -f 2 "$tmp_forbidden"`
+       pkg_info_e `cut -d : -f 3 "$tmp_forbidden"`
 }
 
 # ============= Restore a package if it is temporarily deinstalled =============
 reinstall_restore_if_temporarily_deinstalled ()
 {
-       local backup_pkg pkg
+       local tmp_delete
+       [ $opt_fetch_only = no -a $opt_dry_run = no ] || return 0
        [ -n "$REINSTALL_CURRENTPKG" ] && return
-       backup_pkg=`cat "$REINSTALL_DBNODE_DIR/backedup_pkgfile" 2> /dev/null` || return 0
-       [ -z "$backup_pkg" -o ! -e "$backup_pkg" ] && return
-       pkg=`pkgsys_pkgarc_to_pkgname "$backup_pkg"`
-       if reinstall_chk_forbidden_conflicts "$pkg"
+       tmp_list=${TMPDIR}/reinstall_restore_if_temporarily_deinstalled
+       rm -rf "$tmp_list".*
+       [ -e "$REINSTALL_FROMNODE_DIR/backedup_pkgfile" ] || return 0
+       while read backup_pkg
+       do
+               [ -z "$backup_pkg" -o ! -e "$backup_pkg" ] && continue
+               echo "$backup_pkg" >> $tmp_list.backedup
+               pkg=`pkgsys_pkgarc_to_pkgname "$backup_pkg"`
+               if reinstall_chk_forbidden_conflicts "$pkg"
+               then
+                       echo "$backup_pkg" >> $tmp_list.avoid
+               else
+                       echo "$backup_pkg" >> $tmp_list.restore
+               fi
+       done < $REINSTALL_FROMNODE_DIR/backedup_pkgfile
+       [ -e "$tmp_list.backedup" ] || return 0
+       message_echo "INFO: This port is temporarily deinstalled, so restoration will be attempted."
+       if [ -e "$tmp_list.avoid" ]
        then
-               message_echo "INFO: This port is temporarily deinstalled but avoided because it conflicts with installed packages."
-               return
+               message_echo "INFO: The following backup(s) are avoided because of conflict with installed packages."
+               message_cat < $tmp_list.avoid
+       fi
+       if [ -e "$tmp_list.restore" ]
+       then
+               message_echo "INFO: The following backup(s) will be restored."
+               message_cat < $tmp_list.restore
+               while read backup_pkg
+               do
+                       pkg_add_fF "$backup_pkg" || echo "$backup_pkg" >> $tmp_list.failed
+               done < $tmp_list.restore
+               if [ -e "$tmp_list.failed" ]
+               then
+                       message_echo "WARNING: Failed to restore the following backup, but continuing anyway." >&2
+                       message_cat < $tmp_list.failed
+               fi
        fi
-       message_echo "INFO: This port is temporarily deinstalled, so restoring from the backup."
-       pkg_add_fF "$backup_pkg" && return
-       message_echo "WARNING: Failed to restore the backup, but continuing anyway." >&2
+       :
 }
 
-# ============= Skip reinstallation by showing messages if an origin is in a list =============
+# ============= Skip reinstallation by showing messages if a flavored origin is in a list =============
 reinstall_skip_if_in_a_list ()
 {
-       local message list mode origin_regexp_esc
+       local message list mode
        message=$1
        list=$2
        mode=$3
-       origin_regexp_esc=`str_escape_regexp "$REINSTALL_ORIGIN"`
-       grep -q -E "^$origin_regexp_esc$" "${DBDIR}/$list" 2> /dev/null || return
+       grep -q -Fx "$REINSTALL_ORIGIN" "${DBDIR}/$list" 2> /dev/null || return
        [ "x$mode" = xrestore ] && reinstall_restore_if_temporarily_deinstalled
        reinstall_skip "$message" || :
 }
@@ -91,8 +116,9 @@ reinstall_setup_make_args ()
                done
                [ $opt_avoid_vulner = yes ] || echo 'DISABLE_VULNERABILITIES=yes'
                case $mode in
-               anymode);;
-               ''|distinct)
+               anymode )
+                       ;;
+               '' | distinct )
                        [ $opt_batch_ports_only = yes ] && echo 'BATCH=yes'
                        [ $opt_interactive_ports_only = yes ] && echo 'INTERACTIVE=yes'
                        ;;
@@ -102,6 +128,8 @@ reinstall_setup_make_args ()
                        pkgsys_is_dialog4ports_used && echo 'NO_DIALOG=yes'
                fi
                cat "${DBDIR}/requires/$REINSTALL_ORIGIN/MARG.conf" 2> /dev/null || :
+               flavor=`pkgsys_get_flavor_from_origin "$REINSTALL_ORIGIN"`
+               [ -z "$flavor" ] || echo "FLAVOR=$flavor"
        } | tr '\n' ' '
 }
 
@@ -111,22 +139,28 @@ reinstall_setup_make_envs ()
        cat "${DBDIR}/requires/$REINSTALL_ORIGIN/MENV.conf" 2> /dev/null | tr '\n' ' '
 }
 
+# ============= Common comand to execute make command =============
+_reinstall_make_common ()
+{
+       local mode port_path MAKE_ARGS MAKE_ENVS
+       mode=$1
+       shift
+       MAKE_ARGS=`reinstall_setup_make_args $mode`
+       MAKE_ENVS=`reinstall_setup_make_envs`
+       port_path=`pkgsys_get_portpath_from_origin "$REINSTALL_ORIGIN"`
+       env $MAKE_ENVS make -C "$port_path" "$@" $MAKE_ARGS
+}
+
 # ============= Execute make command without restricting for BATCH or INTERACTIVE ports =============
 reinstall_make_anymode ()
 {
-       local MAKE_ARGS MAKE_ENVS
-       MAKE_ARGS=`reinstall_setup_make_args anymode`
-       MAKE_ENVS=`reinstall_setup_make_envs`
-       env $MAKE_ENVS make -C "${PORTSDIR}/$REINSTALL_ORIGIN" "$@" $MAKE_ARGS
+       _reinstall_make_common anymode "$@"
 }
 
 # ============= Execute make command =============
 reinstall_make ()
 {
-       local MAKE_ARGS MAKE_ENVS
-       MAKE_ARGS=`reinstall_setup_make_args`
-       MAKE_ENVS=`reinstall_setup_make_envs`
-       env $MAKE_ENVS make -C "${PORTSDIR}/$REINSTALL_ORIGIN" "$@" $MAKE_ARGS
+       _reinstall_make_common '' "$@"
 }
 
 # ============= Error process during reinstallation =============
@@ -140,7 +174,7 @@ reinstall_errproc ()
        message_echo "The port/package in concern is $REINSTALL_ORIGPKGTAG." >&2
        [ -n "$msg" ] && message_echo "($msg)" >&2
        message_echo >&2
-       [ -d "${DBDIR}/notes/$REINSTALL_ORIGIN" ] || mkdir -p "${DBDIR}/notes/$REINSTALL_ORIGIN"
+       mkdir -p "${DBDIR}/notes/$REINSTALL_ORIGIN"
        echo "$position" > ${DBDIR}/notes/$REINSTALL_ORIGIN/note_failtre
        database_record_failure "$REINSTALL_ORIGIN" noclean
        fileedit_rm_a_line "$REINSTALL_ORIGIN" "${DBDIR}/stage.loop_list/reinst_todo.remain"
@@ -169,7 +203,7 @@ reinstall_register_stage ()
        local stagetag parentdir
        stagetag=$1
        parentdir=${DBDIR}/status.ports/$REINSTALL_ORIGIN
-       [ -d "$parentdir" ] || mkdir -p "$parentdir"
+       mkdir -p "$parentdir"
        touch "$parentdir/$stagetag"
 }
 
@@ -179,7 +213,7 @@ reinstall_register_stage_complete ()
        local stagetag parentdir
        stagetag=$1
        parentdir=${DBDIR}/status.ports/$REINSTALL_ORIGIN/complete
-       [ -d "$parentdir" ] || mkdir -p "$parentdir"
+       mkdir -p "$parentdir"
        touch "$parentdir/$stagetag"
 }
 
@@ -199,15 +233,15 @@ reinstall_deregister_stage_complete ()
        rm -f "${DBDIR}/status.ports/$REINSTALL_ORIGIN/complete/$stagetag"
 }
 
-# ============= Back up and delete conflicts =============
-# Package names of conflicts are given via stdin. 
+# ============= Back up and delete conflict =============
+# Package names of conflict are given via stdin. 
 reinstall_backup_and_delete_conflicts ()
 {
        local pkg origin origin_regexp_esc backup_pkgdir backup_pkg
        message_echo "INFO: Deinstalling conflicting packages for $REINSTALL_ORIGPKGTAG."
        while read pkg
        do
-               origin=`pkg_info_qo "$pkg"`
+               origin=`pkg_info_flavored_origin "$pkg"`
                message_echo "INFO: Backing up and deleting a conflict, $origin ($pkg)."
                origin_regexp_esc=`str_escape_regexp "$origin"`
                if [ -d "${DBDIR}/requires/$origin" ]
@@ -216,7 +250,7 @@ reinstall_backup_and_delete_conflicts ()
                else
                        backup_pkgdir=${PKGREPOSITORY}
                fi
-               [ -d "$backup_pkgdir" ] || mkdir -p "$backup_pkgdir"
+               mkdir -p "$backup_pkgdir"
                if backup_pkg=`pkgsys_get_backup_pkg "$origin"`
                then
                        message_echo "INFO: backup package already exists as $backup_pkg"
@@ -227,8 +261,8 @@ reinstall_backup_and_delete_conflicts ()
                fi
                grep -v -E "^${origin_regexp_esc}[[:space:]]" "${DBDIR}/deleted_conflicts" \
                        > ${DBDIR}/deleted_conflicts.tmp 2> /dev/null || :
+               printf '%s\t%s\n' "$origin" "$pkg" >> ${DBDIR}/deleted_conflicts.tmp
                mv "${DBDIR}/deleted_conflicts.tmp" "${DBDIR}/deleted_conflicts"
-               printf '%s\t%s\n' "$origin" "$pkg" >> ${DBDIR}/deleted_conflicts
                pkg_delete_f "$pkg" || \
                {
                        message_echo "WARNING: Failed to deinstall $pkg by $PKGSYS_CMD_PKG_DELETE." >&2
@@ -238,41 +272,92 @@ reinstall_backup_and_delete_conflicts ()
        mv "${DBDIR}/deleted_conflicts.tmp" "${DBDIR}/deleted_conflicts"
 }
 
-# ============= Back up and delete remaining actual install conflicts =============
+# ============= Back up and delete remaining actual install conflict =============
 reinstall_backup_and_delete_remaining_install_conflicts ()
 {
-       local stagedir tmp_conflicts
+       local stagedir tmp_conflicts db_conflict
        tmp_conflicts=${TMPDIR}/reinstall_backup_and_delete_remaining_install_conflicts
+       db_conflict=$REINSTALL_DBNODE_DIR/possible_additional_conflist.csv
        message_echo "(Checking installation conflict...)"
+       rm -rf "$db_conflict.tmp" "$tmp_conflicts".*
        stagedir=`database_query_get_makevar_val "$REINSTALL_ORIGIN" STAGEDIR`
-       {
-               ( set -e
-                       cd "$stagedir"
-                       find . -not -type d
-               ) | sed 's|^\.||' | while read filepath
+       pkgsys_get_conflicting_installed_pkgs install "$REINSTALL_ORIGIN" > $tmp_conflicts.pkgs || :
+       ( set -e
+               cd "$stagedir"
+               find . -not -type d
+       ) | sed 's|^\.||' | while read filepath
+       do
+               [ ! -e "$filepath" ] && continue
+               pkg=`pkg_which "$filepath" || :`
+               [ -z "$pkg" ] && continue
+               grep -qFx "$pkg" "$tmp_conflicts.pkgs" && continue
+               origin=`pkg_info_flavored_origin "$pkg"`
+               [ x"$origin" = x"$REINSTALL_ORIGIN" ] && continue
+               printf '%s\t%s\n' "$pkg" "$filepath" >> $db_conflict.tmp
+       done
+       if [ -e "$db_conflict.tmp" ]
+       then
+               while read pkg filepath
                do
-                       [ ! -e "$filepath" ] && continue
-                       pkg=`pkg_which "$filepath" || :`
-                       [ -z "$pkg" ] && continue
-                       origin=`pkg_info_qo "$pkg" || :`
-                       [ x"$origin" = x"$REINSTALL_ORIGIN" ] || echo "$pkg"
-               done
-               pkgsys_get_conflicting_installed_pkgs install "$REINSTALL_ORIGIN"
-       } | sort -u > $tmp_conflicts
+                       message_echo "INFO: Possible additional conflict with $pkg: $filepath"
+               done < $db_conflict.tmp
+               message_echo "INFO: The possible additional conflict packages will be escaped just in case."
+               mv "$db_conflict.tmp" "$db_conflict"
+               cut -f 1 "$db_conflict" >> $tmp_conflicts.pkgs
+       else
+               rm -f "$db_conflict.tmp" "$db_conflict"
+       fi
        while read pkg_conflict
        do
-               fileedit_add_a_line_if_new "$pkg_conflict:$REINSTALL_NEWPKGNAME" \
+               fileedit_add_a_line_if_new "$pkg_conflict:$REINSTALL_ORIGIN:$REINSTALL_NEWPKGNAME" \
                        "${DBDIR}/forbidden_conflicts"
-       done < $tmp_conflicts
-       reinstall_backup_and_delete_conflicts < $tmp_conflicts
+       done < $tmp_conflicts.pkgs
+       reinstall_backup_and_delete_conflicts < $tmp_conflicts.pkgs
+}
+
+# ============= Remove needless possible additional conflict =============
+# Use after installation of the target port and before restoration of its possible additional conflict.
+reinstall_remove_needless_possible_conflict ()
+{
+       local db_conflict db_forbidden suffix tmp_db
+       db_conflict=$REINSTALL_DBNODE_DIR/possible_additional_conflist.csv
+       db_forbidden=${DBDIR}/forbidden_conflicts
+       tmp_db=${TMPDIR}/reinstall_remove_needless_possible_conflict:db
+       [ -e "$db_conflict" ] || return 0
+       if [ ! -e "$db_forbidden" ]
+       then
+               rm -fr "$db_conflict"
+               return
+       fi
+       rm -rf "$db_conflict".*
+       touch $db_conflict.tmp
+       while read pkg filepath
+       do
+               if which -s "$filepath"
+               then
+                       echo printf '%s\t%s\n' "$pkg" "$filepath" >> $db_conflict.tmp
+                       message_echo "WARNING: Unregistered additional conflict with $pkg: $filepath" >&2
+               else
+                       message_echo "INFO: The above notice of the possible additional conflict was needless: $pkg: $filepath"
+               fi
+       done < $db_conflict
+       cut -f 1 "$db_conflict" | sort -u > $tmp_db.conflict_pkg.old
+       cut -f 1 "$db_conflict.tmp" | sort -u > $tmp_db.conflict_pkg.new
+       suffix=`echo ":$REINSTALL_ORIGIN:$REINSTALL_NEWPKGNAME" | str_escape_replaceval_filter`
+       grep -vFx -f "$tmp_db.conflict_pkg.new" "$tmp_db.conflict_pkg.old" | \
+               sed -E "s/$/$suffix/" > $tmp_db.conflict_pkg.needless.filter
+       grep -vFx -f "$tmp_db.conflict_pkg.needless.filter" "$db_forbidden" > $db_forbidden.tmp || :
+       mv "$db_forbidden.tmp" "$db_forbidden"
+       mv "$db_conflict.tmp" "$db_conflict"
+       [ `wc -l < $db_conflict` -gt 0 ] || rm "$db_conflict"
 }
 
-# ============= Restoration of backed up conflicts =============
+# ============= Restoration of backed up conflict =============
 reinstall_restore_conflicts ()
 {
        local origin_current tmpsrc
        origin_current=$1
-       [ $opt_dry_run = yes ] && return
+       [ $opt_fetch_only = no -a $opt_dry_run = no ] || return 0
        [ -e "${DBDIR}/deleted_conflicts" ] || return 0
        tmpsrc=${TMPDIR}/reinstall_restore_conflicts::deleted_conflicts
        cp "${DBDIR}/deleted_conflicts" "$tmpsrc"
@@ -286,9 +371,9 @@ reinstall_restore_conflicts ()
                        | sed -E -f "${DBDIR}/REPLACE.complete_sed_pattern"`
                [ "x$origin_replace" = "x$origin" ] && origin_replace=
                if [ -n "$origin_current" -a "x$origin" = "x$origin_current" ] || \
-                       pkg_info_e "$pkg" || pkg_info_eO "$origin" || \
-                       { [ -n "$origin_orig" ] && pkg_info_eO "$origin_orig"; } || \
-                       { [ -n "$origin_replace" ] && pkg_info_eO "$origin_replace"; }
+                       pkg_info_e "$pkg" || pkgsys_exists_from_orig "$origin" || \
+                       { [ -n "$origin_orig" ] && pkgsys_exists_from_orig "$origin_orig"; } || \
+                       { [ -n "$origin_replace" ] && pkgsys_exists_from_orig "$origin_replace"; }
                then
                        is_to_dereg_from_list=yes
                else
@@ -296,31 +381,54 @@ reinstall_restore_conflicts ()
                fi
                if pkgsys_chk_conflict_by_a_pkg install "$REINSTALL_ORIGIN" "$pkg"
                then
-                       fileedit_add_a_line_if_new "$pkg:$REINSTALL_NEWPKGNAME" "${DBDIR}/forbidden_conflicts"
+                       fileedit_add_a_line_if_new "$pkg:$REINSTALL_ORIGIN:$REINSTALL_NEWPKGNAME" "${DBDIR}/forbidden_conflicts"
                        is_skipped=yes
                elif reinstall_chk_forbidden_conflicts "$pkg"
                then
-                       message_echo "INFO: Restoration of a conflict, $origin ($pkg), is avoided because it conflicts with installed packages."
                        is_skipped=yes
                else
                        is_skipped=no
                fi
+               if [ "$is_skipped" = yes ]
+               then
+                       message_echo "INFO: Restoration of a conflict, $origin ($pkg), is avoided because it conflicts with installed packages."
+               fi
                if [ $is_to_dereg_from_list = yes ]
                then
-                       grep -v -E "[[:space:]]$pkg_regexp_esc$" "${DBDIR}/deleted_conflicts" \
-                               > ${DBDIR}/deleted_conflicts.tmp || :
-                       mv "${DBDIR}/deleted_conflicts.tmp" "${DBDIR}/deleted_conflicts"
+                       origin_current=$origin
+                       pkg_current=`pkgsys_get_installed_pkg_from_origin "$origin"` || :
+                       if [ -z "$pkg_current" -a -n "$origin_orig" ]
+                       then
+                               pkg_current=`pkgsys_get_installed_pkg_from_origin "$origin_orig"` || :
+                               origin_current=$origin_orig
+                       fi
+                       if [ -z "$pkg_current" -a -n "$origin_replace" ]
+                       then
+                               pkg_current=`pkgsys_get_installed_pkg_from_origin "$origin_replace"` || :
+                               origin_current=$origin_replace
+                       fi
+                       pkgname_msg=$pkg
+                       origin_msg=$origin
+                       [ "x$pkg_current" = "x$pkg" ] || pkgname_msg="$pkg => $pkg_current"
+                       [ "x$origin_current" = "x$origin" ] || origin_msg="$origin => $origin_current"
+                       if [ $is_skipped = yes ]
+                       then
+                               message_echo "WARNING: Conflicting package is installed: $origin_msg ($pkgname_msg)"
+                       else
+                               message_echo "INFO: $origin_msg ($pkgname_msg) is already restored."
+                               grep -v -E "[[:space:]]$pkg_regexp_esc$" "${DBDIR}/deleted_conflicts" \
+                                       > ${DBDIR}/deleted_conflicts.tmp || :
+                               mv "${DBDIR}/deleted_conflicts.tmp" "${DBDIR}/deleted_conflicts"
+                       fi
                        continue
                fi
                [ $is_skipped = yes ] && continue
-               origin_regexp_esc=`str_escape_regexp "$origin"`
-               origin_replace_regexp_esc=`str_escape_regexp "$origin_replace"`
-               if grep -q -E -e "^$origin_regexp_esc$" -e "^$origin_replace_regexp_esc$" "${DBDIR}/taboo.all.list" 2> /dev/null
+               if grep -q -Fx -e "$origin" -e "$origin_replace" "${DBDIR}/taboo.all.list" 2> /dev/null
                then
                        message_echo "INFO: Restoration of a conflict, $origin ($pkg), is avoided because it is taboo."
                        continue
                fi
-               message_echo "INFO: Restoring a conflict, $origin ($pkg)."
+               message_echo "INFO: Restoring a former conflict, $origin ($pkg)."
                if ! backup_pkg=`pkgsys_get_backup_pkg "$origin"`
                then
                        message_echo "WARNING: No backup exists, gave up." >&2
@@ -343,7 +451,7 @@ reinstall_are_requirements_ready ()
        [ -e "$REINSTALL_DBNODE_DIR/requirements.all.direct" ] || return 0
        while read origin
        do
-               pkg_info_eO "$origin" || return 1
+               pkgsys_exists_from_orig "$origin" || return 1
        done < $REINSTALL_DBNODE_DIR/requirements.all.direct
 }
 
@@ -358,9 +466,8 @@ reinstall_chk_and_restore_requirements ()
        cat "$REINSTALL_DBNODE_DIR/requirements.all.direct" 2> /dev/null \
                | while read origin
        do
-               pkg_info_eO "$origin" && continue
-               origin_regexp=`str_escape_regexp "$origin"`
-               if grep -q -E "^$origin_regexp$" "${DBDIR}/taboo.all.list" 2> /dev/null
+               pkgsys_exists_from_orig "$origin" && continue
+               if grep -q -Fx "$origin" "${DBDIR}/taboo.all.list" 2> /dev/null
                then
                        message_echo "INFO: Restoration of a requirement [$origin] is avoided because it is set taboo."
                        touch "$tmp_isfailed"
@@ -370,9 +477,8 @@ reinstall_chk_and_restore_requirements ()
                        | sed -E -f "${DBDIR}/REVERSE_REPLACE.complete_sed_pattern"`
                if [ "x$origin_orig" != "x$origin" ]
                then
-                       pkg_info_eO "$origin_orig" && continue
-                       origin_orig_regexp=`str_escape_regexp "$origin_orig"`
-                       if grep -q -E "^$origin_orig_regexp$" "${DBDIR}/taboo.all.list" 2> /dev/null
+                       pkgsys_exists_from_orig "$origin_orig" && continue
+                       if grep -q -Fx "$origin_orig" "${DBDIR}/taboo.all.list" 2> /dev/null
                        then
                                message_echo "INFO: Restoration of a requirement [$origin_orig] is avoided because it is set taboo."
                                touch "$tmp_isfailed"
@@ -382,7 +488,7 @@ reinstall_chk_and_restore_requirements ()
                if ! pkgarc=`pkgsys_get_backup_pkg "$origin"` && \
                        ! pkgarc=`pkgsys_get_backup_pkg "$origin_orig"`
                then
-                       if grep -q -E "^$origin_regexp$" "${DBDIR}/failed.list" 2> /dev/null
+                       if grep -q -Fx "$origin" "${DBDIR}/failed.list" 2> /dev/null
                        then
                                touch "$tmp_isfailed"
                                break
@@ -405,7 +511,7 @@ reinstall_chk_and_restore_requirements ()
                if pkg_add_fF "$pkgarc"
                then
                        grep -v -E "[[:space:]]$pkg_regexp_esc$" "${DBDIR}/deleted_conflicts" \
-                               > ${DBDIR}/deleted_conflicts.tmp || :
+                               > ${DBDIR}/deleted_conflicts.tmp 2> /dev/null || :
                        mv "${DBDIR}/deleted_conflicts.tmp" "${DBDIR}/deleted_conflicts"
                else
                        message_echo "WARNING: Failed to restore by the backed-up package." >&2
@@ -426,8 +532,8 @@ reinstall_pkg_backup ()
                message_echo "-- (Creating temporary backup package for $REINSTALL_ORIGPKGTAG)"
                if backup_pkg=`pkgsys_create_backup_pkg "$pkg" "${DBDIR}/backup_packages"`
                then
-                       echo "$pkg" > $REINSTALL_DBNODE_DIR/backedup_version
-                       echo "$backup_pkg" > $REINSTALL_DBNODE_DIR/backedup_pkgfile
+                       fileedit_add_a_line_if_new "$pkg" "$REINSTALL_FROMNODE_DIR/backedup_version"
+                       fileedit_add_a_line_if_new "$backup_pkg" "$REINSTALL_FROMNODE_DIR/backedup_pkgfile"
                else
                        message_echo "WARNING: Failed to create the backup package, but ignored by hoping success." >&2
                        return 1
@@ -439,46 +545,59 @@ reinstall_pkg_backup ()
 # ============= Deinstallation of the currently installed package =============
 reinstall_deinstall ()
 {
-       [ -n "$REINSTALL_CURRENTPKG" ] || return 0
-       reinstall_chk_stage_complete DEINSTALL && return
+       local tmp_installedpkg installed_pkgs
+       tmp_installedpkg=${TMPDIR}/reinstall_deinstall:installedpkg
+       pkgsys_get_installed_pkg_from_origin "$REINSTALL_ORIGIN" > $tmp_installedpkg
+       [ `wc -l < $tmp_installedpkg` -gt 0 ] || return 0
+       installed_pkgs=`tr '\n' ' ' < $tmp_installedpkg | sed 's/ *$//'`
        if pkgsys_is_necessary_pkgtool "$REINSTALL_ORIGIN"
        then
-               pkg_delete_f "$REINSTALL_CURRENTPKG" || \
+               message_echo "INFO: Deinstalling $installed_pkgs by $PKGSYS_CMD_PKG_DELETE."
+               pkg_delete_f $installed_pkgs || \
                {
-                       message_echo "WARNING: Failed to deinstall $REINSTALL_CURRENTPKG by $PKGSYS_CMD_PKG_DELETE." >&2
+                       message_echo "WARNING: Failed to deinstall." >&2
                }
        else
-               echo "$REINSTALL_CURRENTPKG" | tr ' ' '\n' | grep -v '^$' | while read pkg
+               while read pkg
                do
+                       message_echo "INFO: Deinstalling $pkg by $PKGSYS_CMD_PKG_DELETE." >&2
                        pkg_delete_f "$pkg" || \
                        {
-                               message_echo "WARNING: Failed to deinstall $pkg by $PKGSYS_CMD_PKG_DELETE." >&2
+                               message_echo "WARNING: Failed to deinstall." >&2
                        }
-               done
+               done < $tmp_installedpkg
        fi
-       message_echo "-- (Trying to deinstall by ports to make sure. This usually ends up with warnings.)"
+       message_echo "-- (Trying to deinstall by ports to make sure. This may cause negligible warnings.)"
        reinstall_make deinstall || \
        {
                message_echo "WARNING: Failed to deinstall $REINSTALL_CURRENTPKG by make deinstall." >&2
        }
-       reinstall_register_stage_complete DEINSTALL
+}
+
+# ============= Deinstallation of installed packages for old ports of the current one =============
+reinstall_deinstall_old_ports ()
+{
+       [ -e "$REINSTALL_FROMNODE_DIR/old_origs" ] || return 0
+       while read origin_old
+       do
+               pkgsys_get_installed_pkg_from_origin "$origin_old"
+       done < $REINSTALL_FROMNODE_DIR/old_origs | reinstall_backup_and_delete_conflicts
 }
 
 # ============= Recovery after failure of installation of the new package =============
 reinstall_failed_install_recover ()
 {
-       local backedup_version origin_regexp_esc backup_pkg
+       local backedup_version backup_pkg
        reinstall_chk_stage_complete FAILED_INSTALL.RECOVER && return
        message_echo "INFO: Trying to deinstall the failed/terminated installation (Ignore failures)."
        if [ -n "$REINSTALL_CURRENTPKG" ]
        then
                pkg_delete_f "$REINSTALL_CURRENTPKG" || :
        fi
-       message_echo "INFO: Trying to deinstall by ports to make sure (This usually ends up with warnings)."
+       message_echo "INFO: Trying to deinstall by ports to make sure (This may cause negligible warnings)."
        reinstall_make deinstall || :
-       backedup_version=`cat "$REINSTALL_DBNODE_DIR/backedup_version" 2> /dev/null || :`
-       origin_regexp_esc=`str_escape_regexp "$REINSTALL_ORIGIN"`
-       if grep -q -E "^$origin_regexp_esc$" "${DBDIR}/taboo.all.list" 2> /dev/null
+       backedup_version=`cat "$REINSTALL_FROMNODE_DIR/backedup_version" 2> /dev/null || :`
+       if grep -q -Fx "$REINSTALL_ORIGIN" "${DBDIR}/taboo.all.list" 2> /dev/null
        then
                message_echo "INFO: Restoration of the backup of $backedup_version is avoided because it is taboo."
        elif [ -n "$backedup_version" ]
@@ -488,13 +607,20 @@ reinstall_failed_install_recover ()
                        message_echo "INFO: Restoration of the backup of $backedup_version, is avoided because it conflicts with installed packages."
                else
                        message_echo "INFO: Restoring the backup of $backedup_version."
-                       backup_pkg=`cat "$REINSTALL_DBNODE_DIR/backedup_pkgfile" 2> /dev/null || :`
-                       if [ -z "$backup_pkg" -o ! -e "$backup_pkg" ]
+                       if [ -e "$REINSTALL_FROMNODE_DIR/backedup_pkgfile" ]
                        then
-                               message_echo "WARNING: No backup exists, gave up." >&2
-                       elif ! pkg_add_fF "$backup_pkg"
-                       then
-                               message_echo "WARNING: Failed to restore $backedup_version. Note that your system may experience troubles by this error." >&2
+                               while read backup_pkg
+                               do
+                                       if [ ! -e "$backup_pkg" ]
+                                       then
+                                               message_echo "WARNING: The backup file $backup_pkg doesn't exist, gave up." >&2
+                                       elif ! pkg_add_fF "$backup_pkg"
+                                       then
+                                               message_echo "WARNING: Failed to restore $backedup_version. Note that your system may experience troubles by this error." >&2
+                                       fi
+                               done < $REINSTALL_FROMNODE_DIR/backedup_pkgfile
+                       else
+                               message_echo "WARNING: No backup was saved, gave up." >&2
                        fi
                fi
        fi
@@ -549,9 +675,14 @@ reinstall_closing_operations_after_successful_install ()
                done
        done
        pkgsys_delete_backup_pkg "$REINSTALL_ORIGIN"
-       initial_orig=`cat "$REINSTALL_DBNODE_DIR/initial_orig" 2> /dev/null` || :
-       [ -n "$initial_orig" ] && pkgsys_delete_backup_pkg "$initial_orig"
-       rm -f "$REINSTALL_DBNODE_DIR/backedup_pkgfile"
+       if [ -e "$REINSTALL_FROMNODE_DIR/initial_orig" ]
+       then
+               while read initial_orig
+               do
+                       pkgsys_delete_backup_pkg "$initial_orig"
+               done < $REINSTALL_FROMNODE_DIR/initial_orig
+       fi
+       rm -f "$REINSTALL_FROMNODE_DIR/backedup_pkgfile"
        reinstall_deregister_stage in_postinstall
        database_record_success "$REINSTALL_ORIGIN"
        temp_set_msg_current_stage "${_MSG_CURRENT_STAGE_general}"
@@ -559,18 +690,46 @@ reinstall_closing_operations_after_successful_install ()
        reinstall_register_stage_complete CLOSING_OPERATIONS_AFTER_SUCCESSFUL_INSTALL
 }
 
-# ============= Reinstallation for an origin =============
+# ============= Fetch missing distfiles of a port without sanity check =============
+reinstall_fetch_missing_distfiles ()
+{
+       local port_path tmp_fetch
+       port_path=`pkgsys_get_portpath_from_origin "$REINSTALL_ORIGIN"` || return
+       tmp_fetch=${TMPDIR}/reinstall_fetch_missing_distfiles:fetch.sh
+       tmp_missing_fetch=${TMPDIR}/reinstall_fetch_missing_distfiles:missing_fetch.sh
+       rm -rf "$tmp_fetch.pre"
+       reinstall_make_anymode fetch-list 2> /dev/null > $tmp_fetch.src || return
+       grep '^SHA256[[:space:]]' "$port_path/distinfo" | \
+               sed -E 's/^SHA256[[:space:]]+\(([^)]*)\).*/\1/' | \
+               while read relative_distfile_path
+       do
+               if ! { testhash=`( cd "${DISTDIR}" && sha256 "$relative_distfile_path" ) 2> /dev/null` && \
+                       grep -qxF "$testhash" "$port_path/distinfo"; }
+               then
+                       relative_distfile_path_ptn=`str_escape_regexp "|| echo \"$relative_distfile_path\" not fetched; }"`
+                       if grep -E "$relative_distfile_path_ptn$" "$tmp_fetch.src"
+                       then
+                               subdir_distfile=`dirname "$relative_distfile_path"`
+                               [ "x$subdir_distfile" = x. ] || echo "mkdir -p \"${DISTDIR}/$subdir_distfile\"" >> $tmp_fetch.pre
+                       fi
+               fi
+       done | grep -v '^[[:space:]]*$' > $tmp_fetch.main || :
+       [ -e "$tmp_fetch.pre" ] && sort -u "$tmp_fetch.pre"
+       cat "$tmp_fetch.main"
+}      
+
+# ============= Reinstallation for a flavored origin =============
 reinstall_exec ()
 {
        ( set -e
        REINSTALL_ORIGIN=$1
-       REINSTALL_ORIGIN_REGEXP=`str_escape_regexp "$REINSTALL_ORIGIN"`
        REINSTALL_DBNODE_DIR=${DBDIR}/requires/$REINSTALL_ORIGIN
+       REINSTALL_FROMNODE_DIR=${DBDIR}/moved_from/$REINSTALL_ORIGIN
        REINSTALL_CURRENTPKG=`database_build_update_pkgname "$REINSTALL_ORIGIN" | tr '\n' ' ' | sed 's/ *$//'`
        REINSTALL_IS_CURRENTPKG_LATEST=no
        database_build_is_currentpkg_latest "$REINSTALL_ORIGIN" && REINSTALL_IS_CURRENTPKG_LATEST=yes
        database_build_update_pkgtag "$REINSTALL_ORIGIN"
-       REINSTALL_PKGTAG=`cat "$REINSTALL_DBNODE_DIR/pkgtag"`
+       REINSTALL_PKGTAG=`cat "$REINSTALL_FROMNODE_DIR/pkgtag"`
        REINSTALL_ORIGPKGTAG="$REINSTALL_ORIGIN ($REINSTALL_PKGTAG)"
        REINSTALL_DBSUFFIX=`options_get_dependency_type`.`options_get_dependency_level`
        REINSTALL_NEWPKGNAME=`database_build_get_new_pkgname "$REINSTALL_ORIGIN"`
@@ -582,10 +741,11 @@ reinstall_exec ()
                return
        fi
        reinstall_skip_if_in_a_list 'Skipped because being a leaf port' leaf_ports_to_delete && return
+       rm -f "$REINSTALL_DBNODE_DIR/this_is_skipped_build_requirement"
        if expr "$REINSTALL_CURRENTPKG" : '.* .*' > /dev/null
        then
                message_echo "WARNING: Multiple packages are registered for this port. Reinstallation is needed to fix it." >&2
-       elif grep -q -E "^$REINSTALL_ORIGIN_REGEXP$" "${DBDIR}/damaged_package" 2> /dev/null
+       elif grep -q -Fx "$REINSTALL_ORIGIN" "${DBDIR}/damaged_package" 2> /dev/null
        then
                message_echo "WARNING: Installed files have invalid checksums for this port. Reinstallation is needed to fix it." >&2
        else
@@ -612,10 +772,11 @@ reinstall_exec ()
                                if [ ! -e "$REINSTALL_DBNODE_DIR/necessary_upgrade.${REINSTALL_DBSUFFIX}" ]
                                then
                                        reinstall_restore_if_temporarily_deinstalled
-                                       if [ -e "$REINSTALL_DBNODE_DIR/installed_version" ]
+                                       if [ -e "$REINSTALL_FROMNODE_DIR/installed_version" ]
                                        then
                                                reinstall_skip 'Skipped because being already latest as well as the all requirements'
                                        else
+                                               touch "$REINSTALL_DBNODE_DIR/this_is_skipped_build_requirement"
                                                reinstall_skip 'Skipped because being an only-build-time dependency of already latest packages'
                                        fi
                                        return
@@ -647,7 +808,9 @@ reinstall_exec ()
                return
        fi
        reinstall_skip_if_in_a_list 'Ignored because being taboo' taboo.all.list && return
-       if ! reinstall_are_requirements_ready && ! reinstall_chk_and_restore_requirements
+       if [ $opt_fetch_only = no ] && \
+               ! reinstall_are_requirements_ready && \
+               ! reinstall_chk_and_restore_requirements
        then
                reinstall_restore_if_temporarily_deinstalled
                for tag in all run build none
@@ -661,7 +824,7 @@ reinstall_exec ()
                reinstall_skip 'Skipped because the requirements cannot be ready'
                return
        fi
-       if [ -e "$REINSTALL_DBNODE_DIR/installed_version" ]
+       if [ -e "$REINSTALL_FROMNODE_DIR/installed_version" ]
        then
                insttarget=reinstall
                instdesc='a reinstallation'
@@ -672,6 +835,67 @@ reinstall_exec ()
        temp_set_msg_current_stage "$instdesc process for $REINSTALL_ORIGPKGTAG $PROGRAM_STEP_COUNTER"
        message_target_relations "$REINSTALL_ORIGIN"
        message_echo "------- Starting $instdesc process --------"
+       if ! reinstall_chk_stage_complete CHECK_SANITY
+       then
+               message_echo "Sanity Check..."
+               if ! reinstall_make_anymode check-sanity > ${TMPDIR}/reinstall_exec:check-sanity.msg
+               then
+                       cat "${TMPDIR}/reinstall_exec:check-sanity.msg"
+                       reinstall_restore_if_temporarily_deinstalled
+                       reinstall_errproc 'check sanity'
+                       temp_set_msg_current_stage "${_MSG_CURRENT_STAGE_general}"
+                       if [ $opt_fetch_only = yes ]
+                       then
+                               if [ $opt_inst_by_pkg_if_can = yes ]
+                               then
+                                       if ! reinstall_chk_stage_complete FAILOVER_FETCH_PKG && \
+                                               database_query_is_default_conf "$REINSTALL_ORIGIN"
+                                       then
+                                               message_echo "INFO: The configuration of this port is default, so use of a prebuilt package is attempted."
+                                               func_pkg_inst_remote_verify_fetch=pkg_inst_remote_verify_fetch
+                                               func_pkg_inst_verify_pkg=pkg_inst_verify_pkg
+                                               if [ $opt_use_legacy_pkg_for_missing_pkgng = yes ]
+                                               then
+                                                       func_pkg_inst_remote_verify_fetch=pkg_inst_remote_wild_verify_fetch
+                                                       func_pkg_inst_verify_pkg=pkg_inst_wild_verify_pkg
+                                               fi
+                                               if ! $func_pkg_inst_verify_pkg "$REINSTALL_NEWPKGNAME"
+                                               then
+                                                       message_echo "Trying to fetch the package because of the fetch only mode..."
+                                                       if $func_pkg_inst_remote_verify_fetch "$REINSTALL_NEWPKGNAME"
+                                                       then
+                                                               reinstall_register_stage_complete FAILOVER_FETCH_PKG
+                                                       else
+                                                               message_echo "WARNING: Failed to fetch package for $REINSTALL_NEWPKGNAME"
+                                                       fi
+                                               fi
+                                       fi
+                               fi
+                               if ! reinstall_chk_stage_complete FAILOVER_FETCH
+                               then
+                                       tmp_fetch_missing=${TMPDIR}/reinstall_exec:fetch.sh
+                                       reinstall_fetch_missing_distfiles > $tmp_fetch_missing
+                                       if [ `wc -l < $tmp_fetch_missing` -gt 0 ]
+                                       then
+                                               message_echo "Trying to fetch the distfiles because of the fetch only mode..."
+                                               tmp_fetch_dir=${TMPDIR}/reinstall_exec:fetch_dir
+                                               rm -rf "$tmp_fetch_dir"
+                                               mkdir -p "$tmp_fetch_dir"
+                                               if ( cd "$tmp_fetch_dir" && sh "$tmp_fetch_missing" )
+                                               then
+                                                       reinstall_register_stage_complete FAILOVER_FETCH
+                                               else
+                                                       message_echo "WARNING: Failed to fetch distfiles"
+                                               fi
+                                       fi
+                               fi
+                               message_fetch_only
+                       fi
+                       return
+               fi
+               message_echo
+               reinstall_register_stage_complete CHECK_SANITY
+       fi
        if [ $opt_dry_run = yes ]
        then
                message_dry_run
@@ -691,7 +915,7 @@ reinstall_exec ()
                then
                        if ! reinstall_chk_stage FAILED_INSTALL_BY_PKG
                        then
-                               if [ "x$PKGSYS_USE_PKGNG" = xyes ] \
+                               if [ $opt_fetch_only = no -a "x$PKGSYS_USE_PKGNG" = xyes ] \
                                        && pkgsys_is_necessary_pkgtool "$REINSTALL_ORIGIN"
                                then
                                        if reinstall_deinstall && pkg_is_tool_available && pkg_info_e "$REINSTALL_NEWPKGNAME"
@@ -701,41 +925,59 @@ reinstall_exec ()
                                                reinstall_register_stage FAILED_INSTALL_BY_PKG
                                        fi
                                else
-                                       func_pkg_inst_remote_fetch=pkg_inst_remote_fetch
+                                       func_pkg_inst_remote_verify_fetch=pkg_inst_remote_verify_fetch
                                        func_pkg_inst_remote=pkg_inst_remote
                                        if [ $opt_use_legacy_pkg_for_missing_pkgng = yes ]
                                        then
-                                               func_pkg_inst_remote_fetch=pkg_inst_remote_wild_fetch
+                                               func_pkg_inst_remote_verify_fetch=pkg_inst_remote_wild_verify_fetch
                                                func_pkg_inst_remote=pkg_inst_remote_wild
                                        fi
-                                       if $func_pkg_inst_remote_fetch "$REINSTALL_NEWPKGNAME"
+                                       if $func_pkg_inst_remote_verify_fetch "$REINSTALL_NEWPKGNAME"
                                        then
-                                               pkgsys_get_conflicting_installed_pkgs install "$REINSTALL_ORIGIN" \
-                                                       | reinstall_backup_and_delete_conflicts
-                                               reinstall_pkg_backup || :
-                                               reinstall_register_stage in_add_pkg
-                                               reinstall_deinstall
-                                               if $func_pkg_inst_remote "$REINSTALL_NEWPKGNAME"
+                                               if [ $opt_fetch_only = yes ]
                                                then
-                                                       reinstall_register_stage_complete INSTALL_BY_PKG
+                                                       message_fetch_only
                                                else
-                                                       reinstall_register_stage FAILED_INSTALL_BY_PKG
-                                               fi
-                                               if pkgsys_is_necessary_pkgtool "$REINSTALL_ORIGIN"
-                                               then
-                                                       pkg_is_tool_available || pkg_rescue_tools
+                                                       pkgsys_get_conflicting_installed_pkgs install "$REINSTALL_ORIGIN" \
+                                                               | reinstall_backup_and_delete_conflicts
+                                                       reinstall_pkg_backup || :
+                                                       reinstall_register_stage in_add_pkg
+                                                       reinstall_deinstall_old_ports
+                                                       reinstall_deinstall
+                                                       if $func_pkg_inst_remote "$REINSTALL_NEWPKGNAME"
+                                                       then
+                                                               if database_query_dependency_matching "$REINSTALL_ORIGIN"
+                                                               then
+                                                                       reinstall_register_stage_complete INSTALL_BY_PKG
+                                                               else
+                                                                       message_echo "INFO: The requirements of the package mismatch the configuration."
+                                                                       message_echo "INFO: The installed package will be deleted and installation by port will be attempted instead."
+                                                                       pkg_delete_f "$REINSTALL_NEWPKGNAME" || :
+                                                                       reinstall_register_stage FAILED_INSTALL_BY_PKG
+                                                               fi
+                                                       else
+                                                               reinstall_register_stage FAILED_INSTALL_BY_PKG
+                                                       fi
+                                                       if pkgsys_is_necessary_pkgtool "$REINSTALL_ORIGIN"
+                                                       then
+                                                               pkg_is_tool_available || pkg_rescue_tools
+                                                       fi
                                                fi
                                        else
                                                reinstall_register_stage FAILED_INSTALL_BY_PKG
                                        fi
                                fi
                        fi
-                       if reinstall_chk_stage FAILED_IN_ADD_PKG && reinstall_chk_stage in_add_pkg
+                       if [ $opt_fetch_only = no ]
                        then
-                               reinstall_failed_install_recover
+                               if reinstall_chk_stage FAILED_INSTALL_BY_PKG && \
+                                       reinstall_chk_stage in_add_pkg
+                               then
+                                       reinstall_failed_install_recover
+                               fi
                        fi
                fi
-               if reinstall_chk_stage_complete INSTALL_BY_PKG
+               if [ $opt_fetch_only = no ] && reinstall_chk_stage_complete INSTALL_BY_PKG
                then
                        touch "$REINSTALL_DBNODE_DIR/installed_timestamp"
                        touch "$REINSTALL_DBNODE_DIR/installed_by_pkg"
@@ -746,37 +988,82 @@ reinstall_exec ()
                        return
                fi
                reinstall_deregister_stage in_bypkg
-               message_echo "WARNING: (Re)installation-by-package is unsuccessful, so retrying by using port." >&2
+               if [ $opt_fetch_only = yes ]
+               then
+                       message_echo "INFO: Continue to fetch distfiles in case of installation by port."
+               else
+                       message_echo "WARNING: (Re)installation-by-package is unsuccessful, so retrying by using port." >&2
+               fi
        fi
-       if reinstall_chk_stage in_prebuild
+       if grep -qFx "$REINSTALL_ORIGIN" "${DBDIR}/freeze.all.list" 2> /dev/null
+       then
+               pkg_current=`pkgsys_get_installed_pkg_from_origin "$REINSTALL_ORIGIN"`
+               if [ -z "$pkg_current" ]
+               then
+                       reinstall_restore_if_temporarily_deinstalled
+                       pkg_current=`pkgsys_get_installed_pkg_from_origin "$REINSTALL_ORIGIN"`
+               fi
+               if [ -n "$pkg_current" ]
+               then
+                       message_echo "INFO: The currently installed package $pkg_current is kept because being a port to freeze."
+               else
+                       if pkg_inst_remote_repository_version "$REINSTALL_ORIGIN"
+                       then
+                               message_echo "INFO: The version in the repository is installed because being a port to freeze."
+                               message_echo "WARNING: This action may cause problems due to the version/option mismatch."
+                       else
+                               message_echo "WARNING: Failed install the version in the repository for a port to freeze. Dependents are locked."
+                       fi
+               fi
+               reinstall_skip 'Skipped because being a port to freeze.'
+               return
+       fi
+       if grep -qFx "$REINSTALL_DBNODE_DIR/requirements.all.full" "${DBDIR}/freeze.all.list" 2> /dev/null
        then
-               message_echo "(Restarting the previously terminated pre-build process...)"
-       else
                reinstall_restore_conflicts
-               reinstall_register_stage in_prebuild
+               {
+                       pkgsys_get_conflicting_installed_pkgs build "$REINSTALL_ORIGIN" || :
+                       pkgsys_get_conflicting_installed_pkgs install "$REINSTALL_ORIGIN" || :
+               } | reinstall_backup_and_delete_conflicts
+               if ! database_query_are_requirements_not_locked "$REINSTALL_ORIGIN"
+               then
+                       reinstall_skip 'Skipped because of missing requirements to freeze.'
+                       return
+               fi
+       fi
+       if [ $opt_fetch_only = no ]
+       then
+               if reinstall_chk_stage in_prebuild
+               then
+                       message_echo "(Restarting the previously terminated pre-build process...)"
+               else
+                       reinstall_restore_conflicts
+                       reinstall_register_stage in_prebuild
+               fi
        fi
-       if [ -e "$REINSTALL_DBNODE_DIR/BEFOREBUILD.conf" ] && ! reinstall_chk_stage_complete BEFOREBUILD
+       if [ $opt_fetch_only = no  -a -e "$REINSTALL_DBNODE_DIR/BEFOREBUILD.conf" ] && \
+               ! reinstall_chk_stage_complete BEFOREBUILD
        then
                message_echo "-- BEFOREBUILD operations (start)"
-               sh -e "$REINSTALL_DBNODE_DIR/BEFOREBUILD.conf" || \
-               {
+               if ! sh -e "$REINSTALL_DBNODE_DIR/BEFOREBUILD.conf"
+               then
                        reinstall_restore_if_temporarily_deinstalled
                        reinstall_errproc 'BEFOREBUILD operations'
                        temp_set_msg_current_stage "${_MSG_CURRENT_STAGE_general}"
                        return
-               }
+               fi
                message_echo "-- BEFOREBUILD operations (end)"
                reinstall_register_stage_complete BEFOREBUILD
        fi
-       if ! reinstall_chk_stage_complete CLEAN_BEFORE_BUILD
+       if [ $opt_fetch_only = no ] && ! reinstall_chk_stage_complete CLEAN_BEFORE_BUILD
        then
-               reinstall_make_anymode clean || \
-               {
+               if ! reinstall_make_anymode clean
+               then
                        reinstall_restore_if_temporarily_deinstalled
                        reinstall_errproc 'clean before build'
                        temp_set_msg_current_stage "${_MSG_CURRENT_STAGE_general}"
                        return
-               }
+               fi
                message_echo
                reinstall_register_stage_complete CLEAN_BEFORE_BUILD
        fi
@@ -817,14 +1104,14 @@ reinstall_exec ()
                                                temp_set_msg_current_stage "${_MSG_CURRENT_STAGE_general}"
                                                return
                                        fi
-                                       reinstall_make_anymode checksum || \
-                                       {
+                                       if ! reinstall_make_anymode checksum
+                                       then
                                                reinstall_restore_conflicts "$REINSTALL_ORIGIN"
                                                reinstall_restore_if_temporarily_deinstalled
                                                reinstall_errproc 'checksum'
                                                temp_set_msg_current_stage "${_MSG_CURRENT_STAGE_general}"
                                                return
-                                       }
+                                       fi
                                        reinstall_register_stage_complete FAILED_FETCH.RETRIAL_2
                                fi
                        fi
@@ -833,7 +1120,7 @@ reinstall_exec ()
        fi
        if [ $opt_fetch_only = yes ]
        then
-               message_echo "(Fech only mode)"
+               message_fetch_only
                return
        fi
        reinstall_deregister_stage in_prebuild
@@ -841,10 +1128,10 @@ reinstall_exec ()
        then
                to_skip=no
                case `database_query_get_makevar_val "$REINSTALL_ORIGIN" IS_INTERACTIVE` in
-                       yes   msg_is_interactive='interactive'
+                       yes )   msg_is_interactive='interactive'
                                [ $opt_batch_ports_only = yes ] && to_skip=yes
                                ;;
-                       ''    msg_is_interactive='not interactive'
+                       '' )    msg_is_interactive='not interactive'
                                [ $opt_interactive_ports_only = yes ] && to_skip=yes
                                ;;
                esac
@@ -882,10 +1169,11 @@ reinstall_exec ()
                                reinstall_backup_and_delete_conflicts < ${TMPDIR}/reinstall_exec::conflicts_install
                                is_build_env_modified=yes
                        fi
-                       if pkg_info_eO "$REINSTALL_ORIGIN"
+                       if pkgsys_exists_from_orig "$REINSTALL_ORIGIN"
                        then
                                message_echo "INFO: The currently installed package for this port is deinstalled for retrial because it may have effects on build."
                                reinstall_pkg_backup || :
+                               reinstall_deinstall_old_ports
                                reinstall_deinstall
                                is_build_env_modified=yes
                        fi
@@ -964,19 +1252,16 @@ reinstall_exec ()
        reinstall_pkg_backup || :
        if [ -e "$REINSTALL_DBNODE_DIR/BEFOREDEINSTALL.conf" ] && ! reinstall_chk_stage_complete BEFOREDEINSTALL
        then
-               if [ -n "$REINSTALL_CURRENTPKG" ]
-               then
-                       message_echo "-- BEFOREDEINSTALL operations (start)"
-                       sh -e "$REINSTALL_DBNODE_DIR/BEFOREDEINSTALL.conf" || \
-                       {
-                               reinstall_restore_conflicts "$REINSTALL_ORIGIN"
-                               reinstall_restore_if_temporarily_deinstalled
-                               reinstall_errproc 'BEFOREDEINSTALL operations'
-                               temp_set_msg_current_stage "${_MSG_CURRENT_STAGE_general}"
-                               return
-                       }
-                       message_echo "-- BEFOREDEINSTALL operations (end)"
-               fi
+               message_echo "-- BEFOREDEINSTALL operations (start)"
+               sh -e "$REINSTALL_DBNODE_DIR/BEFOREDEINSTALL.conf" || \
+               {
+                       reinstall_restore_conflicts "$REINSTALL_ORIGIN"
+                       reinstall_restore_if_temporarily_deinstalled
+                       reinstall_errproc 'BEFOREDEINSTALL operations'
+                       temp_set_msg_current_stage "${_MSG_CURRENT_STAGE_general}"
+                       return
+               }
+               message_echo "-- BEFOREDEINSTALL operations (end)"
                reinstall_register_stage_complete BEFOREDEINSTALL
        fi
        if ! reinstall_chk_stage_complete INSTALL
@@ -984,8 +1269,10 @@ reinstall_exec ()
                if pkgsys_is_necessary_pkgtool "$REINSTALL_ORIGIN"
                then
                        reinstall_backup_and_delete_remaining_install_conflicts
+                       reinstall_deinstall_old_ports
                        reinstall_deinstall
                else
+                       reinstall_deinstall_old_ports
                        reinstall_deinstall
                        reinstall_backup_and_delete_remaining_install_conflicts
                fi
@@ -1017,16 +1304,13 @@ reinstall_exec ()
                        if [ -e "$REINSTALL_DBNODE_DIR/AFTERINSTALL.conf" ] && \
                                ! reinstall_chk_stage_complete FAILED_INSTALL.AFTERINSTALL
                        then
-                               if [ -n "$REINSTALL_CURRENTPKG" ]
-                               then
-                                       message_echo "-- AFTERINSTALL operations (start)"
-                                       sh -e "$REINSTALL_DBNODE_DIR/AFTERINSTALL.conf" || \
-                                       {
-                                               message_echo "WARNING: Failed in AFTERINSTALL operations." >&2
-                                               message_echo "---- (The process is continued anyway)"
-                                       }
-                                       message_echo "-- AFTERINSTALL operations (end)"
-                               fi
+                               message_echo "-- AFTERINSTALL operations (start)"
+                               sh -e "$REINSTALL_DBNODE_DIR/AFTERINSTALL.conf" || \
+                               {
+                                       message_echo "WARNING: Failed in AFTERINSTALL operations." >&2
+                                       message_echo "---- (The process is continued anyway)"
+                               }
+                               message_echo "-- AFTERINSTALL operations (end)"
                                reinstall_register_stage_complete FAILED_INSTALL.AFTERINSTALL
                        fi
                        reinstall_restore_conflicts "$REINSTALL_ORIGIN"
@@ -1036,11 +1320,11 @@ reinstall_exec ()
                        return
                fi
        fi
+       reinstall_remove_needless_possible_conflict
        reinstall_restore_if_temporarily_deinstalled
        if ! reinstall_chk_stage_complete UPDATE_CONFLICTS
        then
-               pkg_info_qL "$REINSTALL_CURRENTPKG" | str_escape_regexp_filter | sed 's/^/^/; s/$/$/' \
-                       > ${TMPDIR}/previously_installed_files.grep_pattern
+               pkg_info_qL "$REINSTALL_NEWPKGNAME" > ${TMPDIR}/reinstall_exec:currently_installed_files
                cat "${DBDIR}/backup_pkgarcs.lst" 2> /dev/null \
                        | while read origin_bak pkgpath_bak
                do
@@ -1051,11 +1335,12 @@ reinstall_exec ()
                        elif reinstall_quick_chk_forbidden_conflicts "$pkg_bak"
                        then
                                continue
-                       elif ! pkgsys_chk_match_to_restored_files_by_backup_pkg "$origin_bak" "${TMPDIR}/previously_installed_files.grep_pattern"
+                       elif ! pkgsys_chk_match_to_restored_files_by_backup_pkg \
+                               "$origin_bak" "${TMPDIR}/reinstall_exec:currently_installed_files"
                        then
                                continue
                        fi
-                       fileedit_add_a_line_if_new "$pkg_bak:$REINSTALL_NEWPKGNAME" \
+                       fileedit_add_a_line_if_new "$pkg_bak:$REINSTALL_ORIGIN:$REINSTALL_NEWPKGNAME" \
                                "${DBDIR}/forbidden_conflicts"
                done
                reinstall_register_stage_complete UPDATE_CONFLICTS
index f37e83b..9988079 100644 (file)
@@ -2,7 +2,7 @@
 # ==============================================================================
 # portsreinstall library script
 # - String processing -
-# Copyright (C) 2013-2017 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# Copyright (C) 2013-2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
 # This software is distributed under the 2-Clause BSD License.
 # ==============================================================================
 
@@ -56,7 +56,7 @@ str_linearize_list_and ()
        echo "$*" | sed -E 's/^ +//; s/ +$//; s/ +/, /g; s/, ([^ ]+)$/ and \1/'
 }
 
-# ============= Manipulate an origin name from a diretory path =============
+# ============= Manipulate a flavored origin name from a diretory path =============
 str_dirpath_to_origin ()
 {
        local dbpath portname catpath catname
index 77004fd..365a405 100644 (file)
@@ -2,7 +2,7 @@
 # ==============================================================================
 # portsreinstall library script
 # - Temporary directory and signal trapping -
-# Copyright (C) 2013-2017 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# Copyright (C) 2013-2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
 # This software is distributed under the 2-Clause BSD License.
 # ==============================================================================
 
@@ -13,19 +13,12 @@ TMPDIR=/tmp # Temporary directory
 temp_terminate_process () { :; }
 
 # ============= Warn when the temporary database is obsolete =============
-temp_warn_obsolete_temp_db ()
-{
-       [ "x${DATABASE_IS_OBSOLETE}" = xyes ] || return 0
-       message_echo "WARNING: The Ports tree was updated after construction of the temporary database for ${APPNAME}."
-       message_echo "You should consider executing "
-       message_echo "        ${APPNAME} reset"
-       message_echo "to reset the temporary database unless you have special purposes."
-}
+temp_warn_obsolete_temp_db () { :; }
 
 # ============= Creation of temporary work directories =============
 temp_trap_init ()
 {
-       trap 'errno=$?; temp_warn_obsolete_temp_db >&2; temp_warn_obsolete_temp_db () { :; }; temp_terminate_process >&2; temp_terminate_process () { :; }; rm -rf "${TMPDIR}" 2> /dev/null; [ -n "${DBDIR}" -a x`cat "${DBDIR}/.lock" 2> /dev/null` = x$$ ] && rm -f "${DBDIR}/.lock"; [ $errno -gt 0 -a $errno -ne 130 ] && message_echo "(Error exit by $errno)" >&2; exit $errno' 0 1 2 3 9 15 17 18
+       trap 'errno=$?; temp_warn_obsolete_temp_db >&2; temp_warn_obsolete_temp_db () { :; }; temp_terminate_process $errno >&2; temp_terminate_process () { :; }; rm -rf "${TMPDIR}" 2> /dev/null; [ -n "${DBDIR}" -a x`cat "${DBDIR}/.lock" 2> /dev/null` = x$$ ] && rm -f "${DBDIR}/.lock"; [ $errno -gt 0 -a $errno -ne 130 ] && message_echo "(Exit code: $errno)" >&2; exit $errno' 0 1 2 3 9 15 17 18
        { until TMPDIR=`mktemp -dq /tmp/"${APPNAME}".XXXXXXXX` ; do : ; done ; }
        chgrp "`id -gn`" "${TMPDIR}"
 }
@@ -48,3 +41,14 @@ temp_get_msg_current_stage ()
 {
        cat "${TMPDIR}/TEMP::MSG_CURRENT_STAGE" 2> /dev/null || :
 }
+
+# ============= Reset the termination messages to the common one =============
+temp_reset_termination_messages_common ()
+{
+       temp_terminate_process ()
+       {
+               local errno
+               errno=${1:-0}
+               temp_terminate_process_common "$errno"
+       }
+}
index 82c88f2..156a56f 100644 (file)
@@ -2,87 +2,21 @@
 # ==============================================================================
 # portsreinstall library script
 # - Help messages -
-# Copyright (C) 2013-2017 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# Copyright (C) 2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
 # This software is distributed under the 2-Clause BSD License.
 # ==============================================================================
 
 # ============= Output a short help =============
 usage_short ()
 {
-       fold -s -w `misc_get_console_column_size` << eof
-USAGE: ${APPNAME} [OPTIONS] [--] [command]
-
-[OPTIONS]
- <Group 1: Just show messages and exit without operation>
- -H : Show a long help whose content is the same as the manual page.
- -h : Show this short help.
- -V : Show the current version.
- <Group 2: Effective anytime>
- -a : Suppress messages to be batch-friendly.
- -i : Include new targets to the "needed" list.
- -M : Reset group 4 option settings.
- <Group 3: Effective only with redo command>
- -L : Reload configuration files and reset group 6 option settings.
- -N : Reset group 5 option settings.
- <Group 4: Saved and transferred to restarted runs, renewable by -M option>
- -A : Only non-interactive ports are (re)installed.
- -B : Exclude run-time dependencies in evaluation of dependencies.
- -b : Include build-time dependencies in evaluation of dependencies.
- -C : Skip "make config" by applying default port options if unconfigured.
- -c : Suppress cleaning the temporary database even if its obsolete.
- -D : Suppress entire inspection of distinfo in the ports tree.
- -d : Do not clean up obsolete or unused distfiles.
- -F: Fetch only.
- -f : Force continuation for looped dependency.
- -G : Use prebuilt packages for ports with the default configurations.
- -g : Keep pkg(8) and dialog4ports(1) untouched.
- -I : Only interactive ports are (re)installed.
- -k : Keep ${APPNAME} itself untouched.
- -l : Use legacy packages when prebuilt pkgng packages are missing.
- -n : No operation is carried out (just for seeing what will be done).
- -q : Only new ports and their run-time requirements are reinstalled.
- -s : Build of vulnerable ports are avoided by triggering errors.
- -X : Deselect all deinstallation candidates.
- -Y : Select all deinstallation candidates.
- <Group 5: Saved and transferred to restarted runs, renewable by -N option>
- -O glob1[:glob2[:...]] : Reinstall only target ports themselves.
- -o : Ignore ports which are outside of target scopes of -O, -T or -t options.
- -T glob1[:glob2[:...]] : Reinstall only target ports and their requirements.
- -t glob1[:glob2[:...]] : Reinstall only target ports and their dependents.
- <Group 6: Saved and transferred to restarted runs, renewable by -L option>
- -P : Import settings from pkgtools.conf(5) as the secondary if exists.
- -p : Import settings from pkgtools.conf(5) as the primary if exists (default).
- -Q : Ignore pkgtools.conf(5) even if it exists.
-
- *NOTE*
- The configuration of options annotated as "saved and transferred to restarted runs" are saved in the temporary database by the first run after cleaning the database. In the following runs, the corresponding option settings are loaded from the saved configuration if executed with no option or exactly the same option set as the saved one. Otherwise, the option settings are renewed for possible ones and the others are loaded from the saved configuration. Then the saved configuration is updated with the renewed settings.
-
-[ARGUMENTS]
- command: do [all] (default) | [do] prepare | redo [all] | redo prepare
-          | clean [normal] | clean force | reset [all] | reset keepopts
-          | ok add globs... | ok del globs...
-          | taboo add globs... | taboo del globs...
-          | need add globs... | need del globs...
-          | noneed add globs... | noneed del globs...
-          | reselect leaves | reselect obsolete
-          | save [dir] | load path | glob globs... | options
-          | rmconf globs... | reconf globs... | forget globs...
-          | escape globs... | restore globs...
-          | pkgsanity [globs...]
-          | show todo | show done | show resolved | show failure | show redo
-          | show taboo | show need | show noneed | show restored | show deleted
-          | show conflict | show requirements glob... | show dependents glob...
-          | show initrequirements glob... | show initdependents glob...
-          | show status glob...
-
-[DESCRIPTIONS]
- This utility is an alternative to portupgrade(1) and portmaster(8), and designed to be suitable for reinstallation of all packages after major version upgrade of the system or very long absence of ports upgrade.
- Usually, you can execute with no option nor argument. If portupgrade(1) is installed, compatibility with it is taken into account by importing pkgtools.conf(5) and rebuilding the package database.
-eof
+       usage_short_content | fold -s -w `misc_get_console_column_size`
 }
 
+# ============= Content of the short help =============
+usage_short_content () { :; }
+
 # ============= Output a long help =============
 usage_long ()
 {
-       zcat "`whereis -qm \"${APPNAME}\"`" | nroff -man
+       zcat "${MYPREFIX}/man/man8/${APPNAME}.8.gz" | nroff -man
 }
diff --git a/lib/main/libcommand.sh b/lib/main/libcommand.sh
new file mode 100644 (file)
index 0000000..ee03c91
--- /dev/null
@@ -0,0 +1,503 @@
+#!/bin/sh -e
+# ==============================================================================
+# portsreinstall library script
+# Overlay onto lib/libcommand.sh
+# - Operations of commands as well as check of command line arguments -
+# Copyright (C) 2013-2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# This software is distributed under the 2-Clause BSD License.
+# ==============================================================================
+
+# ============= Check the necessity of opening notice =============
+command_all_chk_need_opening_notice ()
+{
+       [ $COMMAND_MODE = do -o $COMMAND_MODE = redo -o $COMMAND_MODE = forget ]
+}
+
+# ============= Execute command operations before getting the temporary database ready =============
+command_all_exec_before_db_creation ()
+{
+       local COMMAND_RESTART COMMAND_MODE COMMAND_OPERATION
+       COMMAND_RESTART="$@"
+       COMMAND_MODE=${1:-do}
+       shift || :
+       case $COMMAND_MODE in
+       clean )
+               COMMAND_OPERATION=${1:-normal}
+               shift || :
+               _command_parse_args__chk_no_arg $#
+               case $COMMAND_OPERATION in
+               force )
+                       message_echo "INFO: The temporary database is tried to be cleaned up without checking the privilege."
+                       database_maintain_clean_all
+                       message_echo "Done"
+                       exit
+                       ;;
+               esac
+               ;;
+       esac
+}
+
+# ============= Check and parse command line arguments =============
+command_all_parse_args ()
+{
+       local num_args_init
+       num_args_init=$#
+       COMMAND_RESTART="$@"
+       COMMAND_MODE=${1:-do}
+       shift || :
+       case $COMMAND_MODE in
+       clean )
+               COMMAND_OPERATION=${1:-normal}
+               shift || :
+               case $COMMAND_OPERATION in
+               normal )
+                       misc_chk_privilege
+                       ;;
+               esac
+               _command_parse_args__chk_no_arg $#
+               ;;
+       reset )
+               misc_chk_privilege
+               COMMAND_OPERATION=${1:-all}
+               shift || :
+               case $COMMAND_OPERATION in
+               all | keepopts | keepstatus )
+                       ;;
+               *)
+                       message_echo "ERROR: Invalid operation [$COMMAND_OPERATION]; it must be empty, \"all\" or \"keepopts\"." >&2
+                       exit 1
+                       ;;
+               esac
+               _command_parse_args__chk_no_arg $#
+               ;;
+       ok | taboo | freeze | need | noneed )
+               misc_chk_privilege
+               [ $COMMAND_MODE = ok ] && database_query_chk_preparation_completion
+               temp_warn_obsolete_temp_db >&2
+               COMMAND_OPERATION=$1
+               shift || :
+               case $COMMAND_OPERATION in
+               add | del )
+                       ;;
+               '' )
+                       message_echo "ERROR: Missing operation which must be \"add\" or \"del\"." >&2
+                       exit 1
+                       ;;
+               *)
+                       message_echo "ERROR: Invalid operation [$COMMAND_OPERATION]; it must be \"add\" or \"del\"." >&2
+                       exit 1
+                       ;;
+               esac
+               _command_parse_args__chk_glob_args $#
+               ;;
+       reselect )
+               misc_chk_privilege
+               database_query_chk_preparation_completion
+               temp_warn_obsolete_temp_db >&2
+               COMMAND_OPERATION=$1
+               shift || :
+               case $COMMAND_OPERATION in
+               leaves )
+                       if [ -e "${DBDIR}/inspected_ports_only_partially" ]
+                       then
+                               message_echo "ERROR: Leaf ports cannot be analyzed because the dependency inspection is partial." >&2
+                               message_echo "Executing redo command with -N option by disabling -o option fixes this situation." >&2
+                               exit 1
+                       fi
+                       ;;
+               obsolete )
+                       ;;
+               '' )
+                       message_echo "ERROR: Missing operation which must be \"leaves\" or \"obsolete\"." >&2
+                       exit 1
+                       ;;
+               *)
+                       message_echo "ERROR: Invalid operation [$COMMAND_OPERATION]; it must be \"leaves\" or \"obsolete\"." >&2
+                       exit 1
+                       ;;
+               esac
+               _command_parse_args__chk_glob_args $#
+               ;;
+       save )
+               misc_chk_privilege
+               if [ ! -d "${DBDIR}" ]
+               then
+                       message_echo "ERROR: The temporary database has not been created yet." >&2
+                       exit 1
+               fi
+               COMMAND_SAVE_DIR=$1
+               shift || :
+               _command_parse_args__chk_no_arg $#
+               if [ -z "$COMMAND_SAVE_DIR" ]
+               then
+                       message_echo "ERROR: Directory to save the temporary database archive is not specified." >&2
+                       exit 1
+               fi
+               if [ ! -d "$COMMAND_SAVE_DIR" ]
+               then
+                       message_echo "ERROR: Directory [$COMMAND_SAVE_DIR] is not found." >&2
+                       exit 1
+               fi
+               ;;
+       load )
+               misc_chk_privilege
+               if database_maintain_chk_use
+               then
+                       message_echo "ERROR: A temporary database exists." >&2
+                       message_echo "You must execute" >&2
+                       message_echo "        ${APPNAME} clean" >&2
+                       message_echo "before executing \"load\" command." >&2
+                       exit 1
+               fi
+               COMMAND_LOAD_FILE=$1
+               shift || :
+               _command_parse_args__chk_no_arg $#
+               if [ -z "$COMMAND_LOAD_FILE" ]
+               then
+                       message_echo "ERROR: No temporary database archive is specified." >&2
+                       exit 1
+               fi
+               if [ ! -f "$COMMAND_LOAD_FILE" ]
+               then
+                       message_echo "ERROR: No such temporary database archive is found." >&2
+                       exit 1
+               fi
+               COMMAND_LOAD_FILE=`realpath "$COMMAND_LOAD_FILE"`
+               ;;
+       glob )
+               _command_parse_args__chk_glob_args $#
+               ;;
+       options )
+               _command_parse_args__chk_no_arg $#
+               ;;
+       reconf | rmconf | forget | escape | restore )
+               misc_chk_privilege
+               temp_warn_obsolete_temp_db >&2
+               _command_parse_args__chk_glob_args $#
+               ;;
+       pkgsanity )
+               misc_chk_privilege
+               temp_warn_obsolete_temp_db >&2
+               ;;
+       packupgrade )
+               misc_chk_privilege
+               COMMAND_OPERATION=$1
+               shift || :
+               case $COMMAND_OPERATION in
+               create | clean )
+                       _command_parse_args__chk_no_arg $#
+                       ;;
+               crop )
+                       COMMAND_PACKUPGRADE_SAVEPATH=${1:-${PROGRAM}-upgrade.tar.gz}
+                       shift || :
+                       _command_parse_args__chk_no_arg $#
+                       [ ! -d "${COMMAND_PACKUPGRADE_SAVEPATH}" ] ||  COMMAND_PACKUPGRADE_SAVEPATH=${COMMAND_PACKUPGRADE_SAVEPATH}/${PROGRAM}-upgrade.tar.gz
+                       ;;
+               *)
+                       message_echo "ERROR: Invalid operation [$COMMAND_OPERATION]; it must be \"create\" \"crop\" or \"clean\"." >&2
+                       exit 1
+                       ;;
+               esac
+               ;;
+       show )
+               case $COMMAND_SHOW_SUBJECT in
+               todo | done | redo | resolved | failure | deleted | restored | conflict )
+                       database_query_chk_preparation_completion;;
+               esac
+               temp_warn_obsolete_temp_db >&2
+               if ! expr "$1" : '@.*' > /dev/null
+               then
+                       COMMAND_SHOW_SUBJECT=${1:-todo}
+                       shift || :
+               else
+                       COMMAND_SHOW_SUBJECT=todo
+               fi
+               COMMAND_SHOW_OPTIONS=$1
+               if expr "$COMMAND_SHOW_OPTIONS" : '@.*' > /dev/null
+               then
+                       COMMAND_SHOW_DEPTAG=`expr "$COMMAND_SHOW_OPTIONS," : '@\(.*\)' | cut -d , -f 1` || :
+                       COMMAND_SHOW_LEVEL=`expr "$COMMAND_SHOW_OPTIONS," : '@\(.*\)' | cut -d , -f 2` || :
+                       case $COMMAND_SHOW_DEPTAG in
+                       all | run | build | '' )        ;;
+                       *)
+                               message_echo "ERROR: Invalid show option [$COMMAND_SHOW_OPTIONS]." >&2
+                               exit 1
+                               ;;
+                       esac
+                       case $COMMAND_SHOW_LEVEL in
+                       full | direct | '' )    ;;
+                       *)
+                               message_echo "ERROR: Invalid show option [$COMMAND_SHOW_OPTIONS]." >&2
+                               exit 1
+                               ;;
+                       esac
+                       shift || :
+               fi
+               case $COMMAND_SHOW_SUBJECT in
+               todo | done | redo | resolved | failure | taboo | freeze | need | noneed | restored | deleted | conflict )
+                       _command_parse_args__chk_no_arg $#
+                       ;;
+               initrequirements | requirements | initdependents | dependents | conflict_files | status )
+                       _command_parse_args__chk_glob_args $#
+                       ;;
+               *)
+                       message_echo "ERROR: Invalid subject [$COMMAND_SHOW_SUBJECT]." >&2
+                       exit 1
+                       ;;
+               esac
+               ;;
+       all | prepare )
+               COMMAND_DO_MODE=$COMMAND_MODE
+               COMMAND_MODE=do
+               misc_chk_privilege
+               temp_warn_obsolete_temp_db >&2
+               _command_parse_args__chk_no_arg $#
+               ;;
+       redo | do )
+               COMMAND_DO_MODE=${1:-all}
+               shift || :
+               case $COMMAND_DO_MODE in
+               all | prepare );;
+               *)
+                       message_echo "ERROR: Invalid operation mode [$COMMAND_DO_MODE]." >&2
+                       exit 1
+                       ;;
+               esac
+               misc_chk_privilege
+               temp_warn_obsolete_temp_db >&2
+               _command_parse_args__chk_no_arg $#
+               if [ "$COMMAND_DO_MODE" = prepare ]
+               then
+                       COMMAND_RESTART=prepare
+               else
+                       COMMAND_RESTART=
+               fi
+               ;;
+       *)
+               message_echo "ERROR: Invalid command [$COMMAND_MODE]." >&2
+               exit 1
+               ;;
+       esac
+       COMMAND_SHIFT=$(($num_args_init - $#))
+}
+
+# ============= Notify that option settings are reset =============
+command_exec_without_pkgtools__notify_reset_options ()
+{
+       message_echo "NOTE: Option settings are ignored (because of no effect) and reset."
+}
+
+# ============= Execute command operations which do not need package tools =============
+command_all_exec_without_pkgtools ()
+{
+       shift || :
+       case $COMMAND_MODE in
+       clean | load )
+               command_exec_without_pkgtools__notify_reset_options
+               case $COMMAND_MODE in
+               clean )
+                       message_echo "Starting to clean up the temporary database..."
+                       database_maintain_clean_all
+                       ;;
+               load )
+                       message_echo "Starting to load the temporary database from the archive..."
+                       database_maintain_load "$COMMAND_LOAD_FILE"
+                       ;;
+               esac
+               message_echo "Done"
+               exit
+               ;;
+       esac
+}
+
+# ============= Execute command operations which are irrespective of option settings =============
+command_all_exec_irrespective_of_saved_options ()
+{
+       local arcfile
+       shift || :
+       case $COMMAND_MODE in
+       ok )
+               _command_exec_irrespective_of_saved_options__notify_ignored_options
+               command_flexconf_update_ok "$@"
+               exit
+               ;;
+       taboo | freeze | need | noneed )
+               _command_exec_irrespective_of_saved_options__notify_ignored_options
+               mkdir -p "${DBDIR}/journal"
+               echo "$@" >> ${DBDIR}/journal/$COMMAND_MODE
+               case $COMMAND_MODE in
+               taboo )
+                       command_flexconf_update_taboo "$@"
+                       ;;
+               freeze )
+                       command_flexconf_update_freeze "$@"
+                       ;;
+               need )
+                       program_deregister_stage_complete DETERMINE_SPECIFIED_TARGETS
+                       program_deregister_stage_complete ALL_COMPLETE
+                       command_flexconf_update_need "$@"
+                       ;;
+               noneed )
+                       program_deregister_stage_complete INSPECT_PRIMARY_LEAF_PORTS
+                       program_deregister_stage_complete ALL_COMPLETE
+                       command_flexconf_update_noneed "$@"
+                       ;;
+               esac
+               exit
+               ;;
+       reselect )
+               case $COMMAND_OPERATION in
+               leaves )
+                       if ! deinstall_select_leaf_ports_to_delete force
+                       then
+                               case $? in
+                               2 )
+                                       message_echo "INFO: No leaf port is found."
+                                       ;;
+                               3 )
+                                       message_echo "INFO: Leaf ports are undefined because requirements of some ports are not fully inspected."
+                                       ;;
+                               esac
+                       else
+                               program_deregister_stage_complete COLLECT_LEAF_PORTS_TO_DELETE
+                               program_deregister_stage_complete ALL_COMPLETE
+                       fi
+                       ;;
+               obsolete )
+                       if ! deinstall_select_obsolete_ports_to_delete force
+                       then
+                               case $? in
+                               2 )
+                                       message_echo "INFO: No obsolete package is found."
+                                       ;;
+                               esac
+                       else
+                               program_deregister_stage_complete COLLECT_OBSOLETE_PORTS_TO_DELETE
+                               program_deregister_stage_complete ALL_COMPLETE
+                       fi
+                       ;;
+               esac
+               exit
+               ;;
+       save )
+               _command_exec_irrespective_of_saved_options__notify_ignored_options
+               arcfile=`realpath "$COMMAND_SAVE_DIR"`/${APPNAME}_`date +%Y%m%d_%H%M%S`.tar.gz
+               message_echo "Starting to save the temporary database as [$arcfile]..."
+               database_maintain_save "$arcfile"
+               message_echo "Done"
+               exit
+               ;;
+       glob )
+               _command_exec_irrespective_of_saved_options__notify_ignored_options
+               message_echo "Evaluated flavored port origins are as follows:"
+               pkgsys_eval_ports_glob "$@"
+               exit
+               ;;
+       reconf | rmconf | forget | escape | restore | pkgsanity | packupgrade )
+               _command_exec_irrespective_of_saved_options__notify_ignored_options
+               case $COMMAND_MODE in
+               reconf | rmconf )
+                       command_pkgs_port_option_conf "$@"
+                       ;;
+               forget )
+                       command_forget "$@"
+                       ;;
+               escape )
+                       command_pkgs_escape "$@"
+                       ;;
+               restore )
+                       command_pkgs_restore "$@"
+                       ;;
+               pkgsanity )
+                       command_pkgs_pkgsanity "$@"
+                       ;;
+               packupgrade )
+                       command_pkgs_packupgrade
+                       ;;
+               esac
+               message_echo "Done"
+               exit
+               ;;
+       redo )
+               command_do_redo__command_all_exec_irrespective_of_saved_options
+               ;;
+       esac
+}
+
+# ============= Execute command operations which should be done without upgrade of tools =============
+command_all_exec_before_tools_upgrade ()
+{
+       shift || :
+       case $COMMAND_MODE in
+       reset )
+               message_echo "Starting to reset the temporary database by preserving the initial snapshot of installed packages..."
+               if [ ! -d "${DBDIR}" ]
+               then
+                       message_echo "INFO: No temporary database is built yet."
+               else
+                       database_maintain_reset "$COMMAND_OPERATION"
+                       message_echo "INFO: Option settings and taboo/freeze/need/noneed lists are preserved."
+               fi
+               message_echo "Done"
+               exit
+               ;;
+       options )
+               options_show_all
+               exit
+               ;;
+       show )
+               command_show "$@"
+               exit
+               ;;
+       esac
+}
+
+# ============= Execute command operations which must be done before the database construction =============
+command_all_exec_before_build_database ()
+{
+local dstfile
+       case $COMMAND_MODE in
+       do )
+               command_do_do__command_all_exec_before_build_database
+               ;;
+       redo )
+               command_do_redo__command_all_exec_before_build_database
+               ;;
+       esac
+}
+
+# ============= Execute command operations of database construction =============
+command_all_exec_build_database ()
+{
+       case $COMMAND_MODE in
+       do | redo )
+               command_do_prepare
+               ;;
+       esac
+}
+
+# ============= Execute command operations which must be done before the main process =============
+command_all_exec_before_main ()
+{
+       case $COMMAND_MODE in
+       do | redo )
+               case $COMMAND_DO_MODE in
+               prepare )
+                       command_do_end_at_prepare_complete
+                       exit
+                       ;;
+               esac
+               ;;
+       esac
+}
+
+# ============= Execute command operations as the main process =============
+command_all_exec_main ()
+{
+       case $COMMAND_MODE in
+       do | redo )
+               command_do_main
+               command_do_ending_process
+               ;;
+       esac
+}
diff --git a/lib/main/liboptions.sh b/lib/main/liboptions.sh
new file mode 100644 (file)
index 0000000..b25c75c
--- /dev/null
@@ -0,0 +1,75 @@
+#!/bin/sh -e
+# ==============================================================================
+# portsreinstall library script
+# Overlay onto lib/liboptions.sh
+# - Command line options -
+# Copyright (C) 2013-2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# This software is distributed under the 2-Clause BSD License.
+# ==============================================================================
+
+# ============= Database of options which are given at each run and not saved =============
+# [Syntax of option databases]
+# short_name, long_name, variable, defult_vaule, set_value
+# Columns are delimited by tab characters.
+options_db_onetime ()
+{
+       cat << eof
+h      help    opt_help_mode   0       1
+h      short-help      opt_help_mode   0       1
+H      long-help       opt_help_mode   0       2
+V      show-version    opt_show_version        no      yes
+a      batch-mode      opt_batch_mode  no      yes
+N      reset-targets   opt_reset_targets       no      yes
+M      reset-minor-options     opt_reset_minor_options no      yes
+L      reload-conf     opt_reload_conf no      yes
+i      allow-new-targets       opt_allow_new_targets   no      yes
+S      no-opening-message      opt_no_opening_message  no      yes
+eof
+}
+
+# ============= Database of options which are saved and renewable at each run =============
+options_db_saved_and_renewable ()
+{
+       cat << eof
+C      apply-default-config    opt_apply_default_config        no      yes
+A      non-interactive-ports-only      opt_batch_ports_only    no      yes
+I      interactive-ports-only  opt_interactive_ports_only      no      yes
+s      avoid-vulnerability-check       opt_avoid_vulner        no      yes
+q      skip-unchanged-ports    opt_skip_unchanged      no      yes
+b      include-buildtime-dependencies  opt_include_buildtime_dependencies      no      yes
+B      exclude-runtime-dependencies    opt_include_runtime_dependencies        yes     no
+d      keep-distfiles  opt_keep_distfiles      no      yes
+k      suppress-self-upadte    opt_suppress_self_upadte        no      yes
+g      suppress-pkgtools-upadte        opt_suppress_pkgtools_upadte    no      yes
+c      suppress-clean-obsolete-database        opt_suppress_obsolete_db_clean  no      yes
+D      suppress-entire-inspection-distinfo     opt_inspect_entire_distinfo     yes     no
+n      dry-run opt_dry_run     no      yes
+X      deselect-all    opt_dialog_auto no      none
+Y      select-all      opt_dialog_auto no      all
+G      use-prebuilt-package    opt_inst_by_pkg_if_can  no      yes
+l      use-legacy-package-for-missing-pkgng    opt_use_legacy_pkg_for_missing_pkgng    no      yes
+f      disallow-force-continuation-for-looped-dependency       opt_disallow_force_continuation_for_looped_dependency   no      yes
+F      fetch-only      opt_fetch_only  no      yes
+eof
+}
+
+# ============= Database of options which are saved and renewable only at the initial runs of redo command (on target specification) =============
+options_db_saved_and_renewable_in_redo_on_target ()
+{
+       cat << eof
+t      target-and-dependents   opt_target_dependents   ''      :
+T      target-and-requirements opt_target_requirements ''      :
+O      target-only-itself      opt_target_itself       ''      :
+o      only-target-scope       opt_only_target_scope   no      yes
+eof
+}
+
+# ============= Database of options which are saved and renewable only at the initial runs of redo command (on configuration files) =============
+options_db_saved_and_renewable_in_redo_on_conf ()
+{
+       cat << eof
+p      load-pkgtoolsconf-as-default    opt_load_pkgtoolsconf   undef   default
+P      load-pkgtoolsconf-as-override   opt_load_pkgtoolsconf   undef   override
+Q      ignore-pkgtoolsconf     opt_load_pkgtoolsconf   undef   no
+eof
+}
diff --git a/lib/main/libtemp.sh b/lib/main/libtemp.sh
new file mode 100644 (file)
index 0000000..47f2c7c
--- /dev/null
@@ -0,0 +1,18 @@
+#!/bin/sh -e
+# ==============================================================================
+# portsreinstall library script
+# Overlay onto lib/libtemp.sh
+# - Temporary directory and signal trapping -
+# Copyright (C) 2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# This software is distributed under the 2-Clause BSD License.
+# ==============================================================================
+
+# ============= Warn when the temporary database is obsolete =============
+temp_warn_obsolete_temp_db ()
+{
+       [ "x${DATABASE_IS_OBSOLETE}" = xyes ] || return 0
+       message_echo "WARNING: The Ports tree was updated after construction of the temporary database for ${APPNAME}."
+       message_echo "You should consider executing "
+       message_echo "        ${APPNAME} reset keepstatus"
+       message_echo "to reset the temporary database unless you have special purposes."
+}
diff --git a/lib/main/libusage.sh b/lib/main/libusage.sh
new file mode 100644 (file)
index 0000000..4713aea
--- /dev/null
@@ -0,0 +1,89 @@
+#!/bin/sh -e
+# ==============================================================================
+# portsreinstall library script
+# - Help messages -
+# Copyright (C) 2013-2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# This software is distributed under the 2-Clause BSD License.
+# ==============================================================================
+
+# ============= Content of the short help =============
+usage_short_content ()
+{
+       cat << eof
+USAGE: portsreinstall [OPTIONS] [--] [command]
+
+[OPTIONS]
+ <Group 1: Just show messages and exit without operation>
+ -H : Show a long help whose content is the same as the manual page.
+ -h : Show this short help.
+ -V : Show the current version.
+ <Group 2: Effective anytime>
+ -a : Suppress messages to be batch-friendly.
+ -i : Include new targets to the "needed" list.
+ -M : Reset group 4 option settings.
+ -S : Suppress the credit and opening messages.
+ <Group 3: Effective only with redo command>
+ -L : Reload configuration files and reset group 6 option settings.
+ -N : Reset group 5 option settings.
+ <Group 4: Saved and transferred to restarted runs, renewable by -M option>
+ -A : Only non-interactive ports are (re)installed.
+ -B : Exclude run-time dependencies in evaluation of dependencies.
+ -b : Include build-time dependencies in evaluation of dependencies.
+ -C : Skip "make config" by applying default port options if unconfigured.
+ -c : Suppress cleaning the temporary database even if its obsolete.
+ -D : Suppress entire inspection of distinfo in the ports tree.
+ -d : Do not clean up obsolete or unused distfiles.
+ -F: Fetch only.
+ -f : Force continuation for looped dependency.
+ -G : Use prebuilt packages for ports with the default configurations.
+ -g : Keep pkg(8) and dialog4ports(1) untouched.
+ -I : Only interactive ports are (re)installed.
+ -k : Keep portsreinstall itself untouched.
+ -l : Use legacy-style packages when prebuilt modern-style packages are missing.
+ -n : No operation is carried out (just for seeing what will be done).
+ -q : Only new ports and their run-time requirements are reinstalled.
+ -s : Build of vulnerable ports are avoided by triggering errors.
+ -X : Deselect all deinstallation candidates.
+ -Y : Select all deinstallation candidates.
+ <Group 5: Saved and transferred to restarted runs, renewable by -N option>
+ -O glob1[:glob2[:...]] : Reinstall only target ports themselves.
+ -o : Ignore ports which are outside of target scopes of -O, -T or -t options.
+ -T glob1[:glob2[:...]] : Reinstall only target ports and their requirements.
+ -t glob1[:glob2[:...]] : Reinstall only target ports and their dependents.
+ <Group 6: Saved and transferred to restarted runs, renewable by -L option>
+ -P : Import settings from pkgtools.conf(5) as the secondary if exists.
+ -p : Import settings from pkgtools.conf(5) as the primary if exists (default).
+ -Q : Ignore pkgtools.conf(5) even if it exists.
+
+ *NOTE*
+ The configuration of options annotated as "saved and transferred to restarted runs" are saved in the temporary database by the first run after creating/cleaning the database. In the following runs, the corresponding option settings are loaded from the saved configuration if executed with no option or exactly the same option set as the saved one. Otherwise, the option settings are renewed for possible ones and the others are loaded from the saved configuration. Then the saved configuration is updated with the renewed settings.
+
+[ARGUMENTS]
+ command:
+            do [all] (default) | [do] prepare | redo [all] | redo prepare
+          | clean [normal] | clean force | reset [all] | reset keepopts | reset keepstatus
+          | ok add globs... | ok del globs...
+          | taboo add globs... | taboo del globs...
+          | freeze add globs... | freeze del globs...
+          | need add globs... | need del globs...
+          | noneed add globs... | noneed del globs...
+          | reselect leaves | reselect obsolete
+          | save [dir] | load path | glob globs... | options
+          | rmconf globs... | reconf globs... | forget globs...
+          | escape globs... | restore globs...
+          | pkgsanity [globs...]
+          | packupgrade create | packupgrade crop [path] | packupgrade clean
+          | show todo | show done | show resolved | show failure | show redo
+          | show taboo | show need | show noneed | show restored | show deleted
+          | show conflict | show requirements glob... | show dependents glob...
+          | show initrequirements glob... | show initdependents glob...
+          | show conflict_files glob... | show status glob...
+
+[DESCRIPTIONS]
+ This utility is an alternative to portupgrade(1) and portmaster(8), and designed to be suitable for reinstallation of all packages after major version upgrade of the system or very long absence of ports upgrade.
+ Usually, you can execute with no option nor argument. If portupgrade(1) is installed, compatibility with it is taken into account by importing pkgtools.conf(5) and rebuilding the package database.
+
+[ROBUSTNESS AGAINST TERMINATION AND RESTART]
+ Execution of "do", "redo" and "packupgrade" commands can be terminated at any points and restarted from there with the same options saved in the temporary database (independent among utilities). The saved options can be changed by the ways depending on the assigned groups of the options. Some options can be reset only by "redo" command. The options are reset to the default by "clean" and "reset all" commands.
+eof
+}
diff --git a/lib/upgrade/libcommand.sh b/lib/upgrade/libcommand.sh
new file mode 100644 (file)
index 0000000..aac003c
--- /dev/null
@@ -0,0 +1,76 @@
+#!/bin/sh -e
+# ==============================================================================
+# portsreinstall library script
+# Overlay onto lib/libcommand.sh for portsreinstall-upgrade
+# - Operations of commands as well as check of command line arguments -
+# Copyright (C) 2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# This software is distributed under the 2-Clause BSD License.
+# ==============================================================================
+
+# ============= Check and parse command line arguments =============
+command_all_parse_args ()
+{
+       local num_args_init
+       num_args_init=$#
+       COMMAND_RESTART="$@"
+       COMMAND_MODE=${1:-do}
+       shift || :
+       case $COMMAND_MODE in
+       clean )
+               COMMAND_OPERATION=${1:-normal}
+               shift || :
+               case $COMMAND_OPERATION in
+               normal )
+                       misc_chk_privilege
+                       ;;
+               esac
+               _command_parse_args__chk_no_arg $#
+               ;;
+       do | options )
+               _command_parse_args__chk_no_arg $#
+               ;;
+       *)
+               message_echo "ERROR: Invalid command [$COMMAND_MODE]." >&2
+               exit 1
+               ;;
+       esac
+       COMMAND_SHIFT=$(($num_args_init - $#))
+}
+
+# ============= Execute command operations which do not need package tools =============
+command_all_exec_without_pkgtools ()
+{
+       local dbdir_parent 
+       case $COMMAND_MODE in
+       clean )
+               command_exec_without_pkgtools__notify_reset_options
+               message_echo "Starting to clean up the temporary database..."
+               database_maintain_clean_all
+               message_echo "Done"
+               exit
+               ;;
+       esac
+}
+
+# ============= Execute command operations which are irrespective of option settings =============
+command_all_exec_irrespective_of_saved_options ()
+{
+       case $COMMAND_MODE in
+       options )
+               options_show_all
+               exit
+               ;;
+       esac
+}
+
+# ============= Execute command operations as the main process =============
+command_all_exec_main ()
+{
+       case $COMMAND_MODE in
+       do )
+               command_do_main
+               command_do_ending_process
+               ;;
+       esac
+}
+
diff --git a/lib/upgrade/libcommand_do.sh b/lib/upgrade/libcommand_do.sh
new file mode 100644 (file)
index 0000000..c1f6901
--- /dev/null
@@ -0,0 +1,270 @@
+#!/bin/sh -e
+# ==============================================================================
+# portsreinstall library script
+# Overlay onto lib/libcommand_do.sh for portsreinstall-upgrade
+# - "do" command operation -
+# Copyright (C) 2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# This software is distributed under the 2-Clause BSD License.
+# ==============================================================================
+
+# ============= Set up the manifest =============
+command_do_setup_manifest ()
+{
+       local PROGRAM_DEPENDS
+       PROGRAM_DEPENDS=
+       _program_exec_and_record_completion__operation ()
+       {
+               message_section_title "Setting up the list of ports to reinstall"
+               pkg_get_pkgs_timestamps > ${DBDIR}/initial_pkgs_snapshot.csv
+               message_echo
+       }
+       program_exec_and_record_completion SETUP_MANIFEST
+}
+
+# ============= Check of package paths =============
+command_do_chk_pkg_paths ()
+{
+       local PROGRAM_DEPENDS
+       PROGRAM_DEPENDS='SETUP_MANIFEST'
+       _program_exec_and_record_completion__operation ()
+       {
+               message_section_title "Checking the paths of package files"
+               while read -r cmd target argument additional
+               do
+                       case $cmd in
+                               add | addtool )
+                                       if ! pkgpath=`pkgsys_pkgname_to_pkgarc "$opt_packages_dir" "$target"`
+                                       then
+                                               message_echo "ERROR: Package for [$target] is not found. Aborting." >&2
+                                               exit 1
+                                       fi
+                                       additional=$pkgpath
+                                       ;;
+                               delete | delete_pattern )
+                                       argument=
+                                       ;;
+                               *)
+                                       message_echo "ERROR: Invalid command [$cmd $target $argument" >&2
+                                       exit 1
+                       esac
+                       printf '%s\t%s\t%s\t%s\n' "$cmd" "$target" "$argument" "$additional"
+               done < ${ETCDIR}/manifest.lst > ${DBDIR}/stage.loop_list/manifest_pkgpath
+               cp /dev/null "${DBDIR}/stage.loop_list/failed_add"
+               message_echo
+       }
+       program_exec_and_record_completion CHK_PKGS
+}
+
+# ============= (Re)installation of new and reinstalled ports =============
+command_do_reinst_ports ()
+{
+       local PROGRAM_DEPENDS
+       PROGRAM_DEPENDS='CHK_PKGS'
+       _program_exec_restartable_loop_operation__routine ()
+       {
+               local cmd target argument additional target_regexp timestamp_init timestamp_fin pkgtype_init pkgtype_fin target_pkg pkgpath item conflict pkgs_pkgtools
+               cmd=`echo "$1" | cut -f 1`
+               target=`echo "$1" | cut -f 2`
+               argument=`echo "$1" | cut -f 3`
+               additional=`echo "$1" | cut -f 4`
+               target_regexp=`str_escape_regexp "$target"`
+               timestamp_init=`grep -E "^${target_regexp}[[:space:]]" "${DBDIR}/initial_pkgs_snapshot.csv" | cut -f 2`
+               timestamp_fin=`grep -E "^${target_regexp}[[:space:]]" "${ETCDIR}/final_pkgs_snapshot.csv" | cut -f 2`
+               if [ -n "$timestamp_init" -a -n "$timestamp_fin" ]
+               then
+                       pkgtype_init=`expr "$timestamp_init" : '\([^:]*\):' || :`
+                       pkgtype_fin=`expr "$timestamp_fin" : '\([^:]*\):' || :`
+                       if [ -n "$pkgtype_init" -a -n "$pkgtype_fin" -a "x$pkgtype_init" = "x$pkgtype_fin" ]
+                       then
+                               datetime_init=`expr "$timestamp_init" : '[^:]*:\([0-9]*\)' || :`
+                               datetime_fin=`expr "$timestamp_fin" : '[^:]*:\([0-9]*\)' || :`
+                               [ -n "$datetime_init" -a -n "$datetime_fin" -a "$datetime_init" -ge "$datetime_fin" ] && break
+                       fi
+               fi
+               case $cmd in
+                       delete )
+                               origin=$argument
+                               if pkgsys_exists_from_orig "$origin"
+                               then
+                                       target_pkg=`pkgsys_get_installed_pkg_from_origin "$origin"`
+                                       if [ $opt_dry_run = yes ]
+                                       then
+                                               message_echo "Dry run: Delete $target_pkg"
+                                       else
+                                               pkg_delete_f "$target_pkg" || \
+                                                       { message_echo "(Ignored)" >&2; }
+                                       fi
+                               fi
+                               ;;
+                       delete_pattern )
+                               pkg_pattern=$argument
+                               pkg_info_Eg "$pkg_pattern" | while read pkgname
+                               do
+                                       if [ $opt_dry_run = yes ]
+                                       then
+                                               message_echo "Dry run: Delete $pkgname"
+                                       else
+                                               pkg_delete_f "$pkgname" || \
+                                                       { message_echo "(Ignored)" >&2; }
+                                       fi
+                               done
+                               ;;
+                       add )
+                               if ! pkg_info_e "$target"
+                               then
+                                       pkgpath=$additional
+                                       if [ $opt_dry_run = yes ]
+                                       then
+                                               message_echo "Dry run: Add $pkgpath"
+                                       else
+                                               if ! pkg_add_fF "$pkgpath"
+                                               then
+                                                       message_echo "(Continue anyway)" >&2
+                                                       item=`printf '%s\t%s' "$target" "$pkgpath"`
+                                                       fileedit_add_a_line_if_new "$item" "${DBDIR}/stage.loop_list/failed_add"
+                                               fi
+                                       fi
+                               fi
+                               ;;
+                       addtool )
+                               pkgpath=$additional
+                               origin=`expr "$argument" : '\([^|]*\)|'`
+                               conflict=`expr "$argument" : '[^|]*|\(.*\)' | tr '|' '\n'`
+                               pkgs_pkgtools=`{
+                                       echo "$conflict" | while read -r pkg_pattern
+                                       do
+                                               [ -n "$pkg_pattern" ] || continue
+                                               pkg_info_Eg "$pkg_pattern" || :
+                                       done
+                                       pkgsys_get_installed_pkg_from_origin "$origin"
+                               } | sort -u`
+                               if [ $opt_dry_run = yes ]
+                               then
+                                       echo $pkgs_pkgtools | while read pkgname
+                                       do
+                                               message_echo "Dry run: Delete $pkgname (package management tool)"
+                                       done
+                                       message_echo "Dry run: Add $pkgpath (package management tool)"
+                               else
+                                       pkg_delete_f $pkgs_pkgtools || \
+                                               { message_echo "(Ignored)" >&2; }
+                                       pkg_add_tools "$pkgpath" || pkg_rescue_tools
+                               fi
+                               ;;
+               esac
+       }
+       _program_exec_and_record_completion__operation ()
+       {
+               message_section_title "Smart update"
+               program_exec_restartable_loop_operation manifest_pkgpath
+               cp /dev/null "${DBDIR}/stage.loop_list/failed_add_again"
+               message_echo
+       }
+       program_exec_and_record_completion SMART_UPDATE
+}
+
+# ============= Deinstallation of remaining old packages =============
+# This may be needed if clean command was executed in the builder chroot environment.
+command_do_deinst_remining_olg_pkgs ()
+{
+       local PROGRAM_DEPENDS
+       PROGRAM_DEPENDS='SMART_UPDATE'
+       _program_exec_and_record_completion__operation ()
+       {
+               message_section_title "Deinstalling remaining old packages if any..."
+               pkg_get_pkgs_timestamps | \
+                       grep -vE "`pkgsys_pkgtools_pkgs_filter_regexp`"> ${TMPDIR}/current_pkgs_snapshot.csv
+               grep -Fxv -f "${ETCDIR}/final_pkgs_snapshot.csv" "${TMPDIR}/current_pkgs_snapshot.csv" | \
+                       cut -f 1 | while read pkg_old
+               do
+                       pkg_delete_f "$pkg_old"
+               done
+               message_echo
+       }
+       program_exec_and_record_completion DEINST_REMAINING_OLD_PKGS
+}
+
+# ============= Retrial of failed adding packages =============
+command_do_retrial ()
+{
+       local PROGRAM_DEPENDS
+       while [ `wc -l < ${DBDIR}/stage.loop_list/failed_add` -gt 0 ]
+       do
+               rm -f  "${DBDIR}/RETRIAL_ADDING:restart"
+               PROGRAM_DEPENDS='DEINST_REMAINING_OLD_PKGS'
+               _program_exec_restartable_loop_operation__routine ()
+               {
+                       local target pkgpath item
+                       target=`echo "$1" | cut -f 1`
+                       pkgpath=`echo "$1" | cut -f 2`
+                       if ! pkg_info_e "$target"
+                       then
+                               if ! pkg_add_fF "$pkgpath"
+                               then
+                                               message_echo "(Continue anyway)" >&2
+                                               item=`printf '%s\t%s' "$target" "$pkgpath"`
+                                               fileedit_add_a_line_if_new "$item" "${DBDIR}/stage.loop_list/failed_add_again"
+                               fi
+                       fi
+               }
+               _program_exec_and_record_completion__operation ()
+               {
+                       message_section_title "Retrial of failed installation"
+                       program_exec_restartable_loop_operation failed_add
+                       touch "${DBDIR}/stage.loop_list/failed_add_again"
+                       if [ `wc -l < ${DBDIR}/stage.loop_list/failed_add_again` -eq 0 ] || diff -q "${DBDIR}/stage.loop_list/failed_add_again" "${DBDIR}/stage.loop_list/failed_add" > /dev/null 2>/dev/null
+                       then
+                               cp /dev/null "${DBDIR}/stage.loop_list/failed_add"
+                       else
+                               touch "${DBDIR}/RETRIAL_ADDING:restart"
+                               mv "${DBDIR}/stage.loop_list/failed_add_again" "${DBDIR}/stage.loop_list/failed_add"
+                               touch "${DBDIR}/stage.loop_list/failed_add_again"
+                       fi
+                       message_echo
+               }
+               program_exec_and_record_completion RETRIAL_ADDING
+               [ -e "${DBDIR}/RETRIAL_ADDING:restart" ] && program_reset_loop_for_stage RETRIAL_ADDING
+       done
+}
+
+# ============= Main operation of do =============
+command_do_main ()
+{
+       # Set up the manifest
+       command_do_setup_manifest
+
+       # Check of package paths
+       command_do_chk_pkg_paths
+
+       # (Re)installation of new and reinstalled ports
+       command_do_reinst_ports
+
+       # Retrial of failed adding packages
+       [ $opt_dry_run = yes ] || command_do_retrial
+}
+
+# ============= Notice of failure =============
+command_do_failure_notice ()
+{
+       touch "${DBDIR}/stage.loop_list/failed_add_again"
+       if [ `wc -l < ${DBDIR}/stage.loop_list/failed_add_again` -gt 0 ]
+       then
+               message_echo "ERROR: The following packages failed to (re)install." >&2
+               ${DBDIR}/stage.loop_list/failed_add_again | cut -f 1 | message_cat >&2
+               exit 1
+       fi
+}
+
+# ============= Ending process =============
+command_do_ending_process ()
+{
+       command_do_failure_notice
+       temp_terminate_process () { :; }
+       if [ $opt_no_opening_message = yes ]
+       then
+               message_echo "Done as ${APPNAME}"
+               return
+       fi
+       message_section_title "COMPLETELY DONE"
+       message_echo "- E N D -"
+}
diff --git a/lib/upgrade/libmain.sh b/lib/upgrade/libmain.sh
new file mode 100644 (file)
index 0000000..130098f
--- /dev/null
@@ -0,0 +1,34 @@
+#!/bin/sh -e
+# ==============================================================================
+# portsreinstall library script
+# Overlay onto lib/libmain.sh for portsreinstall-upgrade
+# - Common functions of main programs -
+# Copyright (C) 2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# This software is distributed under the 2-Clause BSD License.
+# ==============================================================================
+
+# ============= Set termination messages for special commands =============
+main_set_termination_messages_special ()
+{
+}
+
+# ============= Save the previous configuration if exists =============
+main_save_prev_conf ()
+{
+}
+
+# ============= Load the saved configuration =============
+main_load_conf ()
+{
+       . "${SAVEDCONF}"
+}
+
+# ============= Get complete configuration variable definitions by importing pkgtools.conf(5) if available =============
+main_get_complete_conf ()
+{
+}
+
+# ============= Parse the configuration =============
+main_parse_conf ()
+{
+}
diff --git a/lib/upgrade/libmessage.sh b/lib/upgrade/libmessage.sh
new file mode 100644 (file)
index 0000000..02c9691
--- /dev/null
@@ -0,0 +1,18 @@
+#!/bin/sh -e
+# ==============================================================================
+# portsreinstall library script
+# Overlay onto lib/libmessage.sh for portsreinstall-upgrade
+# - Messages -
+# Copyright (C) 2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# This software is distributed under the 2-Clause BSD License.
+# ==============================================================================
+
+# ============= Output the brief description =============
+message_brief_description ()
+{
+       cat << eof
+ -- Package upgrading script dispatched by portsreinstall,
+ -- The ports upgrading utility for massive forced reinstallation
+ -- And for those who are pursuing the perfect packages environment
+eof
+}
diff --git a/lib/upgrade/liboptions.sh b/lib/upgrade/liboptions.sh
new file mode 100644 (file)
index 0000000..a831ecf
--- /dev/null
@@ -0,0 +1,48 @@
+#!/bin/sh -e
+# ==============================================================================
+# portsreinstall library script
+# Overlay onto lib/liboptions.sh for portsreinstall-upgrade
+# - Command line options -
+# Copyright (C) 2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# This software is distributed under the 2-Clause BSD License.
+# ==============================================================================
+
+# ============= Database of options which are given at each run and not saved =============
+# [Syntax of option databases]
+# short_name, long_name, variable, defult_vaule, set_value
+# Columns are delimited by tab characters.
+options_db_onetime ()
+{
+       cat << eof
+h      help    opt_help_mode   0       1
+h      short-help      opt_help_mode   0       1
+H      long-help       opt_help_mode   0       2
+V      show-version    opt_show_version        no      yes
+a      batch-mode      opt_batch_mode  no      yes
+M      reset-minor-options     opt_reset_minor_options no      yes
+S      no-opening-message      opt_no_opening_message  no      yes
+eof
+}
+
+# ============= Database of options which are saved and renewable at each run =============
+options_db_saved_and_renewable ()
+{
+       cat << eof
+c      suppress-clean-obsolete-database        opt_suppress_obsolete_db_clean  no      yes
+n      dry-run opt_dry_run     no      yes
+eof
+}
+
+# ============= Database of options which are saved and not renewable until the temporary database is cleaned =============
+options_db_saved_and_non_renewable ()
+{
+       cat << eof
+P      packages-dir    opt_packages_dir        ''      :
+eof
+}
+
+# ============= Regularize the option value =============
+options_regularize ()
+{
+       opt_packages_dir=`misc_global_path "$opt_packages_dir"`
+}
diff --git a/lib/upgrade/libusage.sh b/lib/upgrade/libusage.sh
new file mode 100644 (file)
index 0000000..d6cf30d
--- /dev/null
@@ -0,0 +1,43 @@
+#!/bin/sh -e
+# ==============================================================================
+# portsreinstall library script
+# Overlay onto lib/libusage.sh for portsreinstall-upgrade
+# - Help messages -
+# Copyright (C) 2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# This software is distributed under the 2-Clause BSD License.
+# ==============================================================================
+
+# ============= Content of the short help =============
+usage_short_content ()
+{
+       cat << eof
+USAGE: ${APPNAME} [OPTIONS] [--] [command]
+
+[OPTIONS]
+ <Group 1: Just show messages and exit without operation>
+ -H : Show a long help whose content is the same as the manual page.
+ -h : Show this short help.
+ -V : Show the current version.
+ <Group 2: Effective anytime>
+ -a : Suppress messages to be batch-friendly.
+ -M : Reset group 4 option settings.
+ -S : Suppress the credit and opening messages.
+ <Group 3: Saved and transferred to restarted runs, renewable by -M option>
+ -c : Suppress cleaning the temporary database even if its obsolete.
+ -n : No operation is carried out (just for seeing what will be done).
+ <Group 4: Saved and not renewable until cleaning>
+ -P : Directory where the updated packages are located (\${PACKAGES}/\${PKGREPOSITORYSUBDIR} by default (which is usually /usr/ports/packages/All)
+
+[ARGUMENTS]
+ command:database_maintain_save
+            do (default)
+          | clean [normal] | clean force
+          | options
+
+[DESCRIPTIONS]
+ This utility is dispatched from a builder environment to target environments for upgrading packages.
+
+[ROBUSTNESS AGAINST TERMINATION AND RESTART]
+ Execution of this utility can be terminated at any points and restarted from there with the same options saved in the temporary database (independent among utilities). The saved options can be changed by the ways depending on the assigned groups of the options. The options and execution progress are reset to the default by running with "-R" option.
+eof
+}
diff --git a/libexec/order_dependencies.awk b/libexec/order_dependencies.awk
new file mode 100755 (executable)
index 0000000..9f68edc
--- /dev/null
@@ -0,0 +1,97 @@
+#!/usr/bin/env awk
+# ==============================================================================
+# portsreinstall library script
+# - Order the dependency of all ports to install/reinstall -
+# Copyright (C) 2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# This software is distributed under the 2-Clause BSD License.
+# ==============================================================================
+
+BEGIN {
+       it = 0;
+       i = 0;
+}
+{
+       if (NF == 0)
+       {
+               i = 0;
+       }
+       else
+       {
+               if (i == 0)
+               {
+                       target = $0;
+                       sub (/\/requirements.all\.full$/, "", target);
+                       sub (/^\.\//, "", target);
+                       srcikey[it] = target;
+                       srckeyi[target] = it;
+                       it++;
+               }
+               else
+               {
+                       src[it-1,i-1] = $0;
+                       srcimax[it-1] = srcsize[it-1] = i;
+               }
+               i++;
+       }
+}
+END {
+       ntargets = it;
+       norder = 0;
+       order_str = "";
+       icycle = 0;
+       lf_order_str = "";
+       while (1)
+       {
+               is_operated = 0;
+               for (it = 0; it < ntargets; it++)
+               {
+                       if (!(it in srcikey)) continue;
+                       if (srcsize[it] > 0) continue;
+                       is_operated = 1;
+                       target = srcikey[it];
+                       delete srcikey[it];
+                       order[norder++] = target;
+                       order_str = order_str lf_order_str;
+                       order_str = sprintf ("%s%s", order_str, target);
+                       lf_order_str = "\n";
+                       for (jt = 0; jt < ntargets; jt++)
+                       {
+                               for (j = 0; j < srcimax[jt]; j++)
+                               {
+                                       if ((jt,j) in src && src[jt,j] == target)
+                                       {
+                                               delete src[jt,j];
+                                               srcsize[jt]--;
+                                               break;
+                                       }
+                               }
+                       }
+               }
+               if (is_operated == 0) break;
+               icycle++;
+       }
+       reinst_order_list = sprintf ("%s%s", ENVIRON["DBDIR"], "/reinst_order.list.tmp");
+       print order_str > reinst_order_list;
+       unsatisfied = "";
+       for (it = 0; it < ntargets; it++)
+       {
+               if (srcsize[it] == 0) continue;
+               reqs = "";
+               sp_reqs = "";
+               for (i = 0; i < srcimax[it]; i++)
+               {
+                       if ((it,i) in src)
+                       {
+                               reqs = reqs sp_reqs src[it,i];
+                               sp_reqs = ", ";
+                       }
+               }
+               unsatisfied = sprintf ("%s%s [%d] (%s)\n", unsatisfied, srcikey[it], srcsize[it], reqs);
+       }
+       if (unsatisfied != "")
+       {
+               unsatisfied_list = sprintf ("%s%s", ENVIRON["DBDIR"], "/unsatisfied.list");
+               print unsatisfied > unsatisfied_list;
+               exit 1;
+       }
+}
diff --git a/man/portsreinstall-chroot-mount.8 b/man/portsreinstall-chroot-mount.8
new file mode 100644 (file)
index 0000000..d02ca8c
--- /dev/null
@@ -0,0 +1,101 @@
+.\" ==================================================================================
+.\" portsreinstall-chroot-mount(8) manual page
+.\" Copyright (C) 2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+.\" ==================================================================================
+.TH PORTSREINSTALL\-CHROOT\-MOUNT 8 "22 June 2018" "FreeBSD" "FreeBSD System Manager's Manual"
+.SH NAME
+portsreinstall\-chroot\-mount \- Support utility for \fBportsreinstall\fR(8) to mount and unmount a builder environment at the grand host environment
+.SH SYNOPSIS
+.B portsreinstall-chroot-mount
+[
+.I
+OPTIONS
+] [
+.B
+\-\-
+] [
+.I
+command
+]
+.SH DESCRIPTION
+This utility is for assisting \fBportsreinstall\-chroot\fR(8) to mount and unmount a builder environment at the grand host environment in case that the target environment is a \fBchroot\fR(8) or \fBjail\fR(8) virtual environment which does not have sufficient privilege to operate the file systems.
+Execution of this utility will be suggested by \fBportsreinstall\-chroot\fR(8) executed at the target environment.
+The executable file of this utility is installed outside the scope of the search paths, and expected to be launched by specifying the full path.
+.SH ROBUSTNESS AGAINST TERMINATION AND RESTART
+Execution of this utility can be terminated at any points and restarted from there.
+.SH ARGUMENTS
+One of the following \fIcommands\fR can be given for optional operations or confirmation.
+.TP
+\fBmount\fR
+(Default) Mount file systems for the builder \fBchroot\fR(8) environment inside the target \fBchroot\fR(8) or \fBjail\fR(8) environment.
+.TP
+\fBunmount\fR
+Unmount file systems for the builder \fBchroot\fR(8) environment inside the target \fBchroot\fR(8) or \fBjail\fR(8) environment.
+.TP
+.RE
+.SH OPTIONS
+If duplicated or conflicting ones are set, the last ones are effective.
+The end of options can be explicitly specified by \fB\-\-\fR.
+Short options can be given in compact forms, for example, \fB\-V \-a\fR to be \fB\-Va\fR.
+.PD
+.SS Group 1: Just show messages and exit without operation
+.IP \fB\-H\fR
+.PD 0
+.TP
+\fB\-\-long\-help\fR
+Show a long help whose content is the same as the manual page.
+.PD
+.IP \fB\-h\fR
+.PD 0
+.TP
+\fB\-\-help\fR
+.PD 0
+.TP
+\fB\-\-short\-help\fR
+Show a short help.
+.PD
+.IP \fB\-V\fR
+.PD 0
+.TP
+\fB\-\-show\-version\fR
+Show the current version.
+.PD
+.SS Group 2: Effective anytime
+.IP \fB\-a\fR
+.PD 0
+.TP
+\fB\-\-batch\-mode\fR
+Suppress messages so as to be friendly for batch operations.
+Comments are suppressed as much as possible.
+.PD
+.IP \fB\-S\fR
+.PD 0
+.TP
+\fB\-\-no\-opening\-message\fR
+Suppress the credit and opening messages.
+Option \fB\-a\fR takes higher priority over this option.
+.PD
+.SH DETAILS
+.SS Overview
+\fBportsreinstall\-chroot\fR(8) provides functionality to carry out package build at a builder \fBchroot\fR(8) environment which is mounted onto the target environment.
+It is designed to be also executable even when the target is \fBchroot\fR(8) or \fBjail\fR(8) environment although such environment may not have sufficient privilege to operate the file systems.
+In such case, \fBportsreinstall\-chroot\fR(8) once terminates its execution and suggests the user to execute this utility at the grand host environment.
+There is no need to install \fBportsreinstall\fR(8) and its family in the grand host environment, and the user will be suggested to specify the full path to this utility installed in the target \fBchroot\fR(8) or \fBjail\fR(8) environment.
+.SH "ENVIRONMENT VARIABLES"
+See the corresponding section of \fBportsreinstall\fR(8).
+The variables are conveyed to the forked environment from the target host.
+.SH HISTORY
+See the corresponding section of \fBportsreinstall\fR(8).
+This utility first appeared in \fBportsreinstall\fR(8) version 4.0.0.
+.SH "SEE ALSO"
+\fBportsreinstall\fR(8),
+\fBportsreinstall\-chroot\fR(8),
+\fBportsreinstall\-upgrade\fR(8).
+.SH COPYRIGHT
+This software is distributed under the 2-Clause BSD License.
+.PP
+(C)\ 2018\ Mamoru\ Sakaue,\ MwGhennndo,\ All\ Rights\ Reserved.
+.PP
+Email:\ sakaue.mamoru@samurai.mwghennn.net
+.PP
+Homepage:\ http://www.mwghennndo.com/software/portsreinstall/
diff --git a/man/portsreinstall-chroot.8 b/man/portsreinstall-chroot.8
new file mode 100644 (file)
index 0000000..82089e2
--- /dev/null
@@ -0,0 +1,306 @@
+.\" ==================================================================================
+.\" portsreinstall\-chroot(8) manual page
+.\" Copyright (C) 2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+.\" ==================================================================================
+.TH PORTSREINSTALL\-CHROOT 8 "22 June 2018" "FreeBSD" "FreeBSD System Manager's Manual"
+.SH NAME
+portsreinstall\-chroot \- Support utility for \fBportsreinstall\fR(8) to build packages in a virtual environment
+.SH SYNOPSIS
+.B portsreinstall\-chroot
+[
+.I
+OPTIONS
+] [
+.B
+\-\-
+] [
+.I
+command
+]
+.SH DESCRIPTION
+This utility is updates packages based on \fBports\fR(7) by creating and using a \fBchroot\fR(8) environment and \fBportsreinstall\fR(8).
+.SH RESTRICTION
+When this utility is executed inside a \fBchroot\fR(8) or \fBjail\fR(8) virtual environment as the target, the execution MAY be terminated at the process of mounting and unmounting file systems.
+In this case, the user should follow a message which addresses to execute \fBportsreinstall\-chroot\-mount\fR(8) at the grand host environment.
+Note that this utility involves mounting and unmounting operations of unionfs whose implementation is still in a challenging level, and the user MAY find that the detection of the mounting/unmounting privilege is fluctuated, namely, sometimes available and sometimes not.
+If you want to forcibly invalidate the privilege of such operations inside \fBchroot\fR(8) or \fBjail\fR(8) environments, set \fB\-d\fR option.
+.PP
+\fI$basedir\fR/usr/local/share/portsreinstall/bin/portsreinstall\-chroot\-mount
+.PP
+for mounting, and
+.PP
+\fI$basedir\fR/usr/local/share/portsreinstall/bin/portsreinstall\-chroot\-mount unmount
+.PP
+for unmounting, where \fI$basedir\fR denotes the base directory of the target environment.
+Here, the exit code of the termination is 2  for mounting and 3 for unmounting.
+After the mounting or unmounting at the grand host environment, rerun this utility (\fBportsreinstall\-chroot\fR(8)) at the target environment.
+.PP
+If the installation path of \fBportsreinstall\fR(8) in the target environment is configured by non-default PREFIX, environment variable SYSTEMBASE must be defined for telling the base directory of the target environment as
+.PP
+.PD 0
+env SYSTEMBASE=\fI$basedir\fR \\
+.RS
+.PD 0
+\fI$basedir\fR\fI$PREFIX\fR/share/portsreinstall/bin/portsreinstall\-chroot\-mount
+.RE
+.PD 0
+for mounting, and
+.PP
+.PD 0
+env SYSTEMBASE=\fI$basedir\fR \\
+.RS
+.PD 0
+\fI$basedir\fR\fI$PREFIX\fR/share/portsreinstall/bin/portsreinstall\-chroot\-mount unmount
+.RE
+.PD 0
+for unmounting.
+.SH ROBUSTNESS AGAINST TERMINATION AND RESTART
+Execution of the commands except \fBclean\fR and \fBoptions\fR commands can be terminated at any points and restarted from there with the same options saved in the temporary database (independent among utilities). The saved options can be changed by the ways depending on the assigned groups of the options. The options and execution progress are reset to the default by \fBclean\fR command.
+.SH SHELL IN THE BUILDER CHROOT ENVIRONMENT
+The same login shell of the current user (which will be the superuser) is invoked as the login shell in the builder \fBchroot\fR(8) environment.
+For \fBsh\fR(1) and its families, environment variable \fIPS1\fR is modified for distinction from the host environment.
+For \fBtcsh\fR(1) and its families, the configuration file (\fB/root/.cshrc\fR) is modified to add a line for redefining \fBprompt\fR variable for the distinction.
+The original configuration file is backed up as \fB/root/.cshrc.bak\-portsreinstall\-chroot\fR.
+.SH ARGUMENTS
+One of the following \fIcommands\fR can be given for optional operations or confirmation.
+.TP
+\fBdo\fR
+(Default) Execute the whole process from creation of a \fBchroot\fR(8) environment to package update of the host system.
+.TP
+\fBenter\fR
+Just (create, if not yet, and) enter the builder \fBchroot\fR(8) environment.
+If once the upgrade of the host environment was completed, this command enables to reuse the same builder \fBchroot\fR(8) environment for the next upgrade with modified configuration or updated ports tree.
+.TP
+\fBmount\fR
+Just (create, if not yet, and) mount file systems for the builder \fBchroot\fR(8) environment.
+.TP
+\fBunmount\fR
+Just unmount file systems for the builder \fBchroot\fR(8) environment.
+.TP
+\fBsync\fR
+Synchronize the files affecting package installation (packages, distfiles, port options, ports/packages management tools configurations) of the host environment to the builder.
+.TP
+\fBclean\fR
+.PD 0
+.TP
+\fBclean [normal]\fR
+Destroy the builder \fBchroot\fR(8) environment and clean up the temporary database.
+.TP
+\fBclean force\fR
+Attempt to destroy the builder \fBchroot\fR(8) environment and clean up the temporary database without checking the lock and privilege.
+.TP
+\fBoptions\fR
+Show saved option settings and expected effects of option-resetting options \fB\-M\fR.
+With \fB\-a\fR option, the first, second and third columns denote the option-resetting options, reset options and remaining options, respectively.
+.TP
+.RE
+.SH OPTIONS
+If duplicated or conflicting ones are set, the last ones are effective.
+The end of options can be explicitly specified by \fB\-\-\fR.
+Short options can be given in compact forms, for example, \fB\-V \-a\fR to be \fB\-Va\fR.
+.PD
+.TP
+\fB*NOTE*\fR
+Option settings are loaded from the saved configuration (independent of \fBportsreinstall\fR(8)) unless explicitly reset by \fB\-M\fR option.
+The saved options can be checked by \fBportsreinstall-upgrade options\fR command.
+.PD
+.SS Group 1: Just show messages and exit without operation
+.IP \fB\-H\fR
+.PD 0
+.TP
+\fB\-\-long\-help\fR
+Show a long help whose content is the same as the manual page.
+.PD
+.IP \fB\-h\fR
+.PD 0
+.TP
+\fB\-\-help\fR
+.PD 0
+.TP
+\fB\-\-short\-help\fR
+Show a short help.
+.PD
+.IP \fB\-V\fR
+.PD 0
+.TP
+\fB\-\-show\-version\fR
+Show the current version.
+.PD
+.SS Group 2: Effective anytime
+.IP \fB\-a\fR
+.PD 0
+.TP
+\fB\-\-batch\-mode\fR
+Suppress messages so as to be friendly for batch operations.
+Comments are suppressed as much as possible.
+It is noted that log output in build/installation processes are not suppressed.
+.PD
+.IP \fB\-E\fR\ \fIdelimiter(s)\fR
+.PD 0
+.TP
+\fB\-\-extra\-dirs\-delim\fR=\fIdelimiter(s)\fR
+Sets a (set of) custom delimiter character(s) for \fB\-e\fR option.
+The default is comma (",").
+If a string longer than one-character length is set, the all characters are recognized as delimiters.
+.PD
+.IP \fB\-S\fR
+.PD 0
+.TP
+\fB\-\-no\-opening\-message\fR
+Suppress the credit and opening messages.
+Option \fB\-a\fR takes higher priority over this option.
+.PD
+.SS Group 3: Saved and not renewable until cleaning
+.IP \fB\-b\fR
+.PD 0
+.TP
+\fB\-\-basedir\fR
+Specifies the base directory of the \fBchroot\fR(8) environment.
+The default is "/home/.portsreinstall\-chroot".
+.PD
+.IP \fB\-c\fR
+.PD 0
+.TP
+\fB\-\-suppress\-cleaning\-obsolete\-database\fR
+Suppress cleaning the temporary database even if its obsolete.
+This option suppresses the default behavior that the temporary database is automatically cleaned up if it is older than the ports tree or portsreinstall itself is to be upgraded.
+Use of this option may cause unexpected results and basically unrecommended.
+.PD
+.IP \fB\-d\fR
+.PD 0
+.TP
+\fB\-\-invalidate\-mount\-privilege\fR
+Forcibly invalidate the privilege of the current environment for mounting/unmounting file systems.
+This option can be meaningful when this utility is executed inside a \fBchroot\fR(8) or \fBjail\fR(8) virtual environment.
+.PD
+.IP \fB\-e\fR\ \fIdir1\fR[\fB,\fIdir2\fR[\fB,\fR...]]
+.PD 0
+.TP
+\fB\-\-extra\-dirs\fR=\fIdir1\fR[\fB,\fIdir2\fR[\fB,\fR...]]
+Sets extra directories to mount for the chroot environment.
+By default (without this option), /bin, /compat, /etc, /lib, /libexec, /rootm /sbin, /sys, /usr and /var (or their entities if they themselves are symbolic links) as well as file systems overlaying their descendant directories are mounted by read-only nullfs from the host and overlaid by unionfs while /dev, /proc and /tmp are mounted with independent proper file systems.
+This option should be set if any of the above directories contain symbolic links referring to outside of the default directories, or if any package build/installation is customized to refer to outside of them.
+The delimiter is comma (",") by default and changeable by \fB\-E\fR option.
+.PD
+.IP \fB\-P\fR
+.PD 0
+.TP
+\fB\-\-load\-pkgtoolsconf\-as\-override\fR
+Import settings from \fBpkgtools.conf\fR(5) as the secondary.
+This option is effective only when \fBportupgrade\fR(1) is installed.
+For duplicated configurations, values in portsreinstall.conf are applied first and then those in \fBpkgtools.conf\fR(5) are.
+This option overrides preceding \fB\-p\fR option. 
+.PD
+.IP \fB\-p\fR
+.PD 0
+.TP
+\fB\-\-load\-pkgtoolsconf\-as\-default\fR
+Import settings from \fBpkgtools.conf\fR(5) as the primary (default).
+This option is effective only when \fBportupgrade\fR(1) is installed.
+For duplicated configurations, values in \fBpkgtools.conf\fR(5) are applied first and then those in portsreinstall.conf are.
+This option overrides preceding \fB\-P\fR option. 
+.PD
+.IP \fB\-Q\fR
+.PD 0
+.TP
+\fB\-\-ignore\-pkgtoolsconf\fR
+Ignore \fBpkgtools.conf\fR(5) even if it exists.
+.PD
+.SH DETAILS
+.SS Overview
+This utility is a supporting tool of \fBportsreinstall\fR(8) to build packages in a \fBchroot\fR(8) environment "forked" from the host environment which is the final target of upgrading.
+On-the-fly smart entire upgrade of all installed ports and robustness against termination/restart is pursued by this tool.
+.PP
+The forked environment is created by \fBnullfs\fR(5) and \fBmount_unionfs\fR(8) onto the host environment.
+Fetched/deleted distfiles and created/fetched/deleted packages are synchronized at the host to the forked environment.
+The ports options and other configurations of ports management (\fB/etc/make.conf\fR, \fB/usr/local/etc/portsreinstall.conf\fR, \fB/usr/local/etc/pkgtools.conf\fR, \fB/usr/local/etc/pkg.conf\fR and the temporary database of \fBportsreinstall\fR(8) in usual environments) are also synchronized as well.
+.PP
+The execution of \fBdo\fR command proceeds in the following step:
+.TP
+1.
+This utility will create and mount the \fBchroot\fR(8) builder environment.
+.PD
+.TP
+2.
+This utility will enter the builder environment, and the user will be prompted in a shell to complete the upgrade of pakages by \fBportsreinstall\fR(8).
+.PD
+.TP
+3.
+The user will exit from the builder environment when the upgrade is complete.
+.PD
+.TP
+4.
+This utility will create packages and an archive of dispatch script for upgrade.
+.PD
+.TP
+5.
+This utility will synchronize the host environment to the builder about distfiles, pakage files, ports options and other configurations of ports management.
+.PD
+.TP
+6.
+The utility will upgrade the ports in host environment using the created packages and dispatched script set.
+.PD
+.SS Example
+The conventional flow of using this utility will be as follows:
+.PP
+1. In the host (target) environment, update the ports tree and the package repository catalog.
+.RS
+root@[host]#
+.B portsnap fetch update
+.RE
+.RS
+root@[host]#
+.B pkg update
+.RE
+2. Launch a "forked" chroot environment by executing this utility.
+.RS
+root@[host]#
+.B portsreinstall\-chroot
+.RE
+3. Then the user will be prompted in the chroot (builder) environment.
+.RS
+root@[chroot]#
+.RE
+4. In the chroot (builder) environment, upgrade the all pakages completely by \fBportsreinstall\fR (the command line options are just an example; muitiple redoing and reconfiguration of port options and other configuration files of ports management may be required).
+.RS
+root@[chroot]#
+.B portsreinstall -qC
+.RE
+5. Exit from the chroot (builder) environment.
+.RS
+root@[chroot]#
+.B exit
+.RE
+6. When the exit code is zero and the upgrading of ports is complete, following processes will be carried out automatically. Otherwise, the process will be terminated here.
+.PP
+7. Updated packages and dispatch script set will be created by internally invoking \fBportsreinstall packupgrade create\fR and \fBportsreinstall packupgrade archive\fR commands.
+.PP
+8. Then distfiles, pakage files, ports options and other configurations of ports management will be synchronized from the chroot (builder) environment.
+.PP
+9. Then the ports in the host (target) environment will be updated by internally invoking the dispatched script set.
+.SH "ENVIRONMENT VARIABLES"
+.TP
+.B SYSTEMBASE
+(Used only when the target environment is a virtual environment implemented by \fBchroot\fR(8) or \fBjail\fR(8))
+The base directory of the target environment at its grand host environment.
+This variable is referred by portsreinstall\-chroot\-mount, which is to be executed in the grand host environment of the target environment.
+The default is the two-levels higher directory of PREFIX applied for installation of \fBportsreinstall\fR(8) in the target environment.
+.PP
+See also the corresponding section of \fBportsreinstall\fR(8).
+The variables are conveyed to the forked environment from the target host.
+.SH HISTORY
+See the corresponding section of \fBportsreinstall\fR(8).
+This utility first appeared in \fBportsreinstall\fR(8) version 4.0.0.
+.SH "SEE ALSO"
+\fBchroot\fR(8)
+\fBportsreinstall\fR(8),
+\fBportsreinstall\-chroot\-mount\fR(8),
+\fBportsreinstall\-upgrade\fR(8).
+.SH COPYRIGHT
+This software is distributed under the 2-Clause BSD License.
+.PP
+(C)\ 2018\ Mamoru\ Sakaue,\ MwGhennndo,\ All\ Rights\ Reserved.
+.PP
+Email:\ sakaue.mamoru@samurai.mwghennn.net
+.PP
+Homepage:\ http://www.mwghennndo.com/software/portsreinstall/
diff --git a/man/portsreinstall-upgrade.8 b/man/portsreinstall-upgrade.8
new file mode 100644 (file)
index 0000000..5dc7377
--- /dev/null
@@ -0,0 +1,153 @@
+.\" ==================================================================================
+.\" portsreinstall-upgrade(8) manual page
+.\" Copyright (C) 2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+.\" ==================================================================================
+.TH PORTSREINSTALL\-UPGRADE 8 "22 June 2018" "FreeBSD" "FreeBSD System Manager's Manual"
+.SH NAME
+portsreinstall\-upgrade \- Support utility for \fBportsreinstall\fR(8) to update a target environment using packages built in a builder environment
+.SH SYNOPSIS
+.B portsreinstall-upgrade
+[
+.I
+OPTIONS
+] [
+.B
+\-\-
+] [
+.I
+command
+]
+.SH DESCRIPTION
+This utility applies updates of packages to a target environment using packages built in a builder environment.
+The executable file of this utility is installed outside the scope of the search paths, and dispatched from the builder environment to target environments by \fBportsreinstall packupgrade create\fR command followed by \fBportsreinstall packupgrade crop\fR command.
+.SH ROBUSTNESS AGAINST TERMINATION AND RESTART
+Execution of this utility can be terminated at any points and restarted from there with the same options saved in the temporary database (independent among utilities). The saved options can be changed by the ways depending on the assigned groups of the options. The options and execution progress are reset to the default by running with \fB\-R\fR option.
+.SH ARGUMENTS
+One of the following \fIcommands\fR can be given for optional operations or confirmation.
+.TP
+\fBdo\fR
+(Default) Apply the update of packages.
+.TP
+\fBclean\fR
+.PD 0
+.TP
+\fBclean [normal]\fR
+Clean up the temporary database.
+.TP
+\fBclean force\fR
+Attempt to clean up the temporary database without checking the lock and privilege.
+.TP
+\fBoptions\fR
+Show saved option settings and expected effects of option-resetting options \fB\-M\fR.
+With \fB\-a\fR option, the first, second and third columns denote the option-resetting options, reset options and remaining options, respectively.
+.TP
+.RE
+.SH OPTIONS
+If duplicated or conflicting ones are set, the last ones are effective.
+The end of options can be explicitly specified by \fB\-\-\fR.
+Short options can be given in compact forms, for example, \fB\-V \-a\fR to be \fB\-Va\fR.
+.PD
+.TP
+\fB*NOTE*\fR
+Option settings are loaded from the saved configuration (independent of \fBportsreinstall\fR(8)) unless explicitly reset by \fB\-M\fR option.
+The saved options can be checked by \fBportsreinstall-upgrade options\fR command.
+.PD
+.SS Group 1: Just show messages and exit without operation
+.IP \fB\-H\fR
+.PD 0
+.TP
+\fB\-\-long\-help\fR
+Show a long help whose content is the same as the manual page.
+.PD
+.IP \fB\-h\fR
+.PD 0
+.TP
+\fB\-\-help\fR
+.PD 0
+.TP
+\fB\-\-short\-help\fR
+Show a short help.
+.PD
+.IP \fB\-V\fR
+.PD 0
+.TP
+\fB\-\-show\-version\fR
+Show the current version.
+.PD
+.SS Group 2: Effective anytime
+.IP \fB\-a\fR
+.PD 0
+.TP
+\fB\-\-batch\-mode\fR
+Suppress messages so as to be friendly for batch operations.
+Comments are suppressed as much as possible.
+It is noted that log output in build/installation processes are not suppressed.
+.PD
+.IP \fB\-M\fR
+.PD 0
+.TP
+\fB\-\-reset\-minor\-options\fR
+Reset option settings for minor controls.
+Option settings for group 4 are once reset and replaced with the newly specified ones.
+Check the saved options by \fBportsreinstall options\fR command before specifying this option.
+.PD
+.IP \fB\-S\fR
+.PD 0
+.TP
+\fB\-\-no\-opening\-message\fR
+Suppress the credit and opening messages.
+Option \fB\-a\fR takes higher priority over this option.
+.PD
+.SS Group 3: Saved and transferred to restarted runs, renewable by \-M option
+Option settings in this group are saved at the first \fBdo\fR or \fBprepare\fR run, and transferred to the following runs.
+Reset of the saved values for this group is available by appending \fB\-M\fR with newly specified options.
+.IP \fB\-c\fR
+.PD 0
+.TP
+\fB\-\-suppress\-cleaning\-obsolete\-database\fR
+Suppress cleaning the temporary database even if its obsolete.
+This option suppresses the default behavior that the temporary database is automatically cleaned up if it is older than the ports tree or portsreinstall itself is to be upgraded.
+Use of this option may cause unexpected results and basically unrecommended.
+.PD
+.IP \fB\-n\fR
+.PD 0
+.TP
+\fB\-\-dry\-run\fR
+No operation is carried out (just for seeing what will be done).
+This option is effective for \fBdo\fR command so that no deinstallation and (re)installation process is actually carried out.
+By this option, ports/packages to be deinstalled or (re)installed can be confirmed without making changes to the current situation of packages.
+.PD
+.SS Group 4: Saved and not renewable until cleaning
+.IP \fB\-P\fR
+.PD 0
+.TP
+\fB\-\-packages\-dir\fR
+Specifies the directory where packages created by the builder environment are located.
+The default is ${PACKAGES}/${PKGREPOSITORYSUBDIR} by default (which is usually /usr/ports/packages/All).
+.PD
+.SH DETAILS
+.SS Overview
+This utility is a supporting tool of \fBportsreinstall\fR(8) to apply packages updates to a target environment using packages built by a builder environment using \fBportsreinstall packupgrade create\fR command followed by \fBportsreinstall packupgrade crop\fR command.
+On-the-fly smart entire upgrade of all installed ports and robustness against termination/restart is pursued by this tool.
+.PP
+The update proceeds from the lowest level of the dependence hierarchy to the highest, where for each port the old version and conflicts are first deinstalled and then the new version is installed.
+Obsolete and leaf ports are deinstalled at the final stage.
+.PD
+.SH "ENVIRONMENT VARIABLES"
+See the corresponding section of \fBportsreinstall\fR(8).
+The variables are conveyed to the forked environment from the target host.
+.SH HISTORY
+See the corresponding section of \fBportsreinstall\fR(8).
+This utility first appeared in \fBportsreinstall\fR(8) version 4.0.0.
+.SH "SEE ALSO"
+\fBportsreinstall\fR(8),
+\fBportsreinstall\-chroot\fR(8),
+\fBportsreinstall\-chroot\-mount\fR(8).
+.SH COPYRIGHT
+This software is distributed under the 2-Clause BSD License.
+.PP
+(C)\ 2018\ Mamoru\ Sakaue,\ MwGhennndo,\ All\ Rights\ Reserved.
+.PP
+Email:\ sakaue.mamoru@samurai.mwghennn.net
+.PP
+Homepage:\ http://www.mwghennndo.com/software/portsreinstall/
index 6b90943..5f385ea 100644 (file)
@@ -1,8 +1,8 @@
 .\" ==================================================================================
-.\" ports reinstall installation guide
-.\" Copyright (C) 2010-2017 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+.\" portsreinstall(8) manual page
+.\" Copyright (C) 2010-2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
 .\" ==================================================================================
-.TH PORTSREINSTALL 8 "22 May 2017" "FreeBSD" "FreeBSD System Manager's Manual"
+.TH PORTSREINSTALL 8 "?? June 2018" "FreeBSD" "FreeBSD System Manager's Manual"
 .SH NAME
 portsreinstall \- ports upgrading utility for massive forced reinstallation
 .SH SYNOPSIS
@@ -19,14 +19,35 @@ command
 ]
 .SH DESCRIPTION
 This utility is an alternative to \fBportupgrade\fR(1) and \fBportmaster\fR(8), and designed to be suitable for reinstallation/upgrade of all packages after major version upgrade of the system or very long absence of ports upgrade, or for entire correction of confusion among installed packages.
-.SH NOTATIONS
- A \fIglob\fR is an extended regular expression or a shell\-type glob pattern matching either of a unique name, package names or port origins.
- The glob syntax is compatible with \fBportupgrade\fR(1) and its accompaniments such as \fBportsdb\fR(1), \fBpkg_glob\fR(1) and \fBports_glob\fR(1).
- If a glob starts with a colon ":", the following string is parsed as an extended regular expression, and otherwise a shell\-type glob.
- A shell\-type glob is evaluated by matching an asterisk "*" to an arbitrary string of an arbitrary length, a question mark "?" to an arbitrary single character, characters "..." enclosed in a bracket "[...]" to a single character as one of the characters and characters "..." in a bracket "[!...]" to a single character matching none of the characters.
- Here, the evaluation of the bracket is actually done by passing it to an extended regular expression by simply converting the prefix "[!" to "[^".
- A glob is recognized as a unique name (package name without the version part) if no slash "/" or any special character for an extended regular expression or a shell\-type glob is included in the pattern.
- For example, all of "zip" "zip\-3.?", "zip\-*", "zip\-[0\-9]*" and ":^zip\-[[:digit:]]+\.*" can match "zip\-3.0"; "archivers/unzip*" can match both of "archivers/unzip" and "archivers/unzip\-iconv".
+.SH ROBUSTNESS AGAINST TERMINATION AND RESTART
+Execution of \fBdo\fR, \fBredo\fR and \fBpackupgrade\fR commands can be terminated at any points and restarted from there with the same options saved in the temporary database (independent among utilities). The saved options can be changed by the ways depending on the assigned groups of the options. Some options can be reset only by \fBredo\fR command. The options are reset to the default by \fBclean\fR and \fBreset all\fR commands.
+.SH FLAVOR SUPPORT
+As of the release time of this software, the flavor support of the Ports Collection has many incomplete features.
+Therefore, users should note that problems may arrise due to the specification changes related to flavors.
+Currenly, coexistence with \fBportupgrade\fR(1) is suspended due to the lack of flavor support.
+The same port configuration options of the same ports are shared among the all flavors because they are not distinguishable in the current implementation of the Ports Collection.
+.SH GLOB PATTERNS
+A \fIglob\fR is an extended regular expression or a shell\-type glob pattern matching either of a unique name, package names, or unflavored port origins possibly followed by flaver.
+The format of a \fIglob\fR may be either:
+.RS
+.IP \fIunique_name_glob\fR
+.IP \fIpackage_name_glob\fR
+.IP \fIport_origin_glob\fR
+.IP \fIport_origin_glob@flaver_glob\fR
+.IP \fI:unique_name_regexp\fR
+.IP \fI:package_name_regexp\fR
+.IP \fI:port_origin_regexp\fR
+.IP \fI:port_origin_regexp@flaver_regexp\fR
+.RE
+where each regular expression (*_regexp) and glob (_glob) pattern must not include any at sign (@).
+Port origin patterns without at sign match all available flavors if deined.
+As long as the specified port origin pattern represents ports wihout available flavor, the glob syntax is compatible with \fBportupgrade\fR(1) and its accompaniments such as \fBportsdb\fR(1), \fBpkg_glob\fR(1) and \fBports_glob\fR(1).
+If a glob starts with a colon ":", the following string is parsed as an extended regular expression, and otherwise a shell\-type glob.
+A shell\-type glob is evaluated by matching an asterisk "*" to an arbitrary string of an arbitrary length, a question mark "?" to an arbitrary single character, characters "..." enclosed in a bracket "[...]" to a single character as one of the characters and characters "..." in a bracket "[!...]" to a single character matching none of the characters.
+Here, the evaluation of the bracket is actually done by passing it to an extended regular expression by simply converting the prefix "[!" to "[^".
+A glob is recognized as a unique name (package name without the version part) if no slash "/" or any special character for an extended regular expression or a shell\-type glob is included in the pattern.
+For example, all of "zip" "zip\-3.?", "zip\-*", "zip\-[0\-9]*" and ":^zip\-[[:digit:]]+\.*" can match "zip\-3.0"; "archivers/unzip*" can match both of "archivers/unzip" and "archivers/unzip\-iconv".
+When the \fIglob\fR should match the all flavors of a port, a regular expression can be used such as ":devel/py-setuptools(|@.*)".
 .SH ARGUMENTS
 One of the following \fIcommands\fR can be given for optional operations or confirmation.
 .TP
@@ -34,7 +55,7 @@ One of the following \fIcommands\fR can be given for optional operations or conf
 .PD 0
 .TP
 \fBdo all\fR
-Full execution (default).
+(Default) Full execution.
 .TP
 \fBprepare\fR
 .PD 0
@@ -59,18 +80,23 @@ In case of restarting a stopped \fBredo prepare\fR process, execute by \fBprepar
 Clean up the temporary database.
 .TP
 \fBclean force\fR
-Clean up the temporary database without checking the privilege.
+Attempt to clean up the temporary database without checking the lock and privilege.
 .TP
 \fBreset\fR
 .PD 0
 .TP
 \fBreset all\fR
 Reset the temporary database by preserving the initial snapshot of installed packages.
-This is for a rescue in case that some ports or the temporary database is broken.
+This command can be used to restart reinstallation when the ports tree is updated after the previous run or to rescue the temporary database from destruction.
 .TP
 \fBreset keepopts\fR
-Reset the temporary database by preserving the initial snapshot of installed packages and option settings.
-This is for a rescue in case that some ports or the temporary database is broken.
+Reset the temporary database by preserving the initial snapshot of installed packages, option settings and manually added \fBtaboo\fR/\fBneed\fR/\fBnoneed\fR ports.
+This command can be used to restart reinstallation when the ports tree is updated after the previous run or to rescue the temporary database from destruction.
+.TP
+\fBreset keepstatus\fR
+Reset the temporary database by preserving the progress status to reuse for unchanged successfully (re)installed ports.
+The initial snapshot of installed packages, option settings and manually added \fBtaboo\fR/\fBneed\fR/\fBnoneed\fR ports are preserved in the same way as \fBreset keepopts\fR command.
+This command can be used to more smartly restart reinstallation when the ports tree is updated after the previous run.
 .TP
 \fBok add\fR \fIglob1\fR [\fIglob2\fR ...]
 Register manually resolved ports.
@@ -85,14 +111,24 @@ Register taboo ports that must not be built or newly (re)installed.
 The port globs are separated from each other by comma or space.
 Registration to be "taboo" practically invalidates "necessary" registered by \fBnoneed add\fR command.
 Ports specified in the HOLD section in the configuration file are protected from deinstallation.
-The port globs are separated from each other by comma or space.
-This functionality is intended to avoid manually deinstalled ports because of confliction or ports whose build or installation operations can damage the system, e.g., by flooding the file systems or kernel panic.
+This functionality is intended to avoid manually deinstalled conflict ports or ports whose build or installation operations can damage the system, e.g., by flooding the file systems or kernel panic.
 This command is for temporal definitions and permanent definitions should be given as TABOO_* values in ${LOCALBASE}/etc/portsreinstall.conf instead.
 .TP
 \fBtaboo del\fR \fIglob1\fR [\fIglob2\fR ...]
 Deregister taboo ports.
 The port globs are separated from each other by comma or space.
 .TP
+\fBfreeze add\fR \fIglob1\fR [\fIglob2\fR ...]
+Register ports to freeze that must not be built but the package installtion by any available version may be safe.
+If the specified ports failed to (re)install by packages, build of their dependents are also suppressed.
+The port globs are separated from each other by comma or space.
+This functionality is intended to build of ports which can damage the system, e.g., by flooding the file systems or kernel panic, while their installed packages will not be harmful.
+This command is for temporal definitions and permanent definitions should be given as FREEZE_* values in ${LOCALBASE}/etc/portsreinstall.conf instead.
+.TP
+\fBfreeze del\fR \fIglob1\fR [\fIglob2\fR ...]
+Deregister ports to freeze.
+The port globs are separated from each other by comma or space.
+.TP
 \fBneed add\fR \fIglob1\fR [\fIglob2\fR ...]
 Register necessary ports that should be newly installed if not yet and kept installed even if being obsolete.
 The port globs are separated from each other by comma or space.
@@ -136,7 +172,7 @@ Load a temporary database archive.
 Note that the currently temporary database is removed.
 .TP
 \fBglob\fR \fIglob\fR [\fIglob2\fR ...]
-Evaluate port globs and show matched origins both for installed and uninstalled packages.
+Evaluate port globs and show matched flavored origins both for installed and uninstalled packages.
 .TP
 \fBoptions\fR
 Show saved option settings and expected effects of option-resetting options \fB\-L\fR, \fB\-M\fR and \fB\-N\fR.
@@ -146,14 +182,16 @@ With \fB\-a\fR option, the first, second and third columns denote the option-res
 Reset port options for the specified ports to the default and reset affected parts in the temporary database.
 .TP
 \fBreconf\fR \fIglob\fR [\fIglob2\fR ...]
-Reconfigure port options for the specified ports and reset affected parts in the temporary database.
+Reconfigure port options for the specified ports.
+The specified ports are re-inspected even when the options are unchanged or undefined.
+All affected ports are inspected again in the following runs by \fBdo\fR or \fBredo\fR command.
 .TP
 \fBforget\fR \fIglob\fR [\fIglob2\fR ...]
 Try to let the temporary database forget about the specified ports as much as possible.
 Concretely, the data on each of the specified ports and their requirements/dependents is unless initially installed or required by other preserved ports.
 This command is mainly for removing information on ports which had been added due to \fB\-i\fR option or \fBneed add\fR command but have become unneeded again.
 In advance to executing this command, deinstallation for the specified ports should be completed by \fBnoneed add\fR command followed by \fBredo\fR command.
-It is noted that ports registered by \fBok\fR, \fBtaboo\fR and \fBnoneed\fR commands are NOT deleted.
+It is noted that ports registered by \fBok\fR, \fBtaboo\fR, \fBfreeze\fR and \fBnoneed\fR commands are NOT deleted.
 Internal tables used for \fBshow\fR command keep their information regardless of this command.
 .TP
 \fBpkgsanity\fR [\fIglob\fR ...]
@@ -162,7 +200,7 @@ If arguments \fIglobs\fR are given, only the matching packages are examined.
 For each insane package, the user is queried whether to reinstall it forcedly in the following do/redo runs.
 The default choice is "yes" for packages which have any ELF binaries or include files changed or any type of files overwritten by other packages, and "no" for the others.
 Insane packages already assigned to be reinstalled are skipped.
-With \fB\-a\fR enabled, all insane packages are assigned to be the above mentioned default and the output is given in a form that the first to fourth columns denote the package name, port origin, whether assigned to be reinstalled (yes or no), and file path with a notice, respectively.
+With \fB\-a\fR enabled, all insane packages are assigned to be the above mentioned default and the output is given in a form that the first to fourth columns denote the package name, flavored port origin, whether assigned to be reinstalled (yes or no), and file path with a notice, respectively.
 It is noted that this sanity check can detect some configuration or cache files which are changed during normal use and need not to be recovered.
 .TP
 \fBescape\fR \fIglob\fR [\fIglob2\fR ...]
@@ -173,6 +211,26 @@ The escaped packages are registered as taboo as same as \fBtaboo add\fR \fIglob\
 Restore packages specified by \fIglobs\fR escaped by \fBescape\fR command.
 The escaped packages are deregistered from taboo as same as \fBtaboo del\fR \fIglob\fR [\fIglob2\fR ...].
 .TP
+\fBpackupgrade\fR \fBcreate\fR
+Create packages of the all reinstalled or newly installed ports (at a "builder" environment) with a set of scripts for upgrading another system with the same initial configuration of installed packages ("target" environment).
+One of typical examples of application can be such that the builder is a "forked" jail/chroot system constructed onto a host system by using nullfs and unionfs and the target is the host system (Refer to "Package build in a chroot system" Section).
+Another typical example can be such that the builder is one node of a cluster system and the targets are the other nodes.
+If the execution is terminated before completion, it can be restarted from the terminated point by re-running this command.
+The created packages are saved at ${PACKAGES}/${PKGREPOSITORYSUBDIR}, which is usually /usr/ports/packages/All.
+In order to crop the created set of scripts, \fBpackupgrade\fR \fBcrop\fR command must be executed.
+.TP
+\fBpackupgrade\fR \fBcrop\fR [\fIpath\fR]
+Crop the created set of scripts as a tar.gz archive, where its path name is specified by \fIpath\fR argument (if \fIpath\fR is a directory, the file name is set to "portsreinstall-upgrade.tar.gz"; the default of \fIpath\fR is the current directory).
+This command must be executed after completion of \fBpackupgrade\fR \fBcreate\fR command.
+The obtained archive is to be conveyed to the target together with the created packages.
+Then "portsreinstall-upgrade.sh" obtained by extracting the archive is to be run at the target.
+.TP
+\fBpackupgrade\fR \fBclean\fR
+Reset the execution progress of \fBpackupgrade\fR \fBcreate\fR command and discard the internally saved created set of scripts.
+This does not affect any already cropped sets of scripts or created packages.
+This command is provided for cases that ports/packages are reinstalled or reconfigured during/after the execution of \fBpackupgrade\fR \fBcreate\fR command.
+After execution of this command, \fBpackupgrade\fR \fBcreate\fR command will overwrite the packages by creating them again.
+.TP
 \fBshow\fR [\fIsubject\fR] [@[\fBrun\fR|\fBbuild\fR|\fBall\fR][,[\fBdirect\fR|\fBfull\fR]]] [\fIarguments\fR]
 Show the list of ports to be reinstalled.
 The applied scope of dependencies can be controlled by "show option" proceeded by "@"; \fBrun\fR, \fBbuild\fR and \fBall\fR employ the run\-time, build\-time or both-time ones, respectively; \fBdirect\fR and \fBfull\fR include only the direct or fully recursive ones, respectively.
@@ -183,67 +241,77 @@ The following \fIsubject\fR's are available.
 .TP
 \fBtodo\fR
 Ports to be reinstalled in the current do/redo process (default).
-With \fB\-a\fR option, the first and second columns denote the origin and initial/new/current package name, respectively.
+With \fB\-a\fR option, the first and second columns denote the flavored origin and initial/new/current package name, respectively.
 .TP
 \fBdone\fR
 Ports which have been already reinstalled to be up-to-date with their all requirements.
-With \fB\-a\fR option, the first and second columns denote the origin and initial/new/current package name, respectively.
+With \fB\-a\fR option, the first and second columns denote the flavored origin and initial/new/current package name, respectively.
 .TP
 \fBresolved\fR
 Manually reinstalled ports registered by \fBok\fR command.
-With \fB\-a\fR option, the first and second columns denote the origin and initial/new/current package name, respectively.
+With \fB\-a\fR option, the first and second columns denote the flavored origin and initial/new/current package name, respectively.
 .TP
 \fBfailure\fR
 Failed ports.
-With \fB\-a\fR option, the first, second and third columns denote the origin, initial/new/current package name, failed make target and manually resolved status (yes or no), respectively.
+With \fB\-a\fR option, the first, second and third columns denote the flavored origin, initial/new/current package name, failed make target and manually resolved status (yes or no), respectively.
 .TP
 \fBredo\fR
 Ports to be reinstalled after success in any of their failed requirements.
-With \fB\-a\fR option, the first and second columns denote the origin and initial/new/current package name, respectively.
+With \fB\-a\fR option, the first and second columns denote the flavored origin and initial/new/current package name, respectively.
 .TP
 \fBtaboo\fR
 Taboo ports registered by \fBtaboo\fR command.
-With \fB\-a\fR option, the first and second columns denote the origin and initial/new/current package name, respectively.
+With \fB\-a\fR option, the first and second columns denote the flavored origin and initial/new/current package name, respectively.
+.TP
+\fBfreeze\fR
+Taboo ports registered by \fBfreeze\fR command.
+With \fB\-a\fR option, the first and second columns denote the flavored origin and initial/new/current package name, respectively.
 .TP
 \fBneed\fR
 Necessary ports registered by \fBneed\fR command.
-With \fB\-a\fR option, the first and second columns denote the origin and initial/new/current package name, respectively.
+With \fB\-a\fR option, the first and second columns denote the flavored origin and initial/new/current package name, respectively.
 .TP
 \fBnoneed\fR
 Unnecessary ports registered by \fBnoneed\fR command.
-With \fB\-a\fR option, the first and second columns denote the origin and initial/new/current package name, respectively.
+With \fB\-a\fR option, the first and second columns denote the flavored origin and initial/new/current package name, respectively.
 .TP
 \fBrestored\fR
 Leaf, obsolete or unneeded ports which had been once deleted but are to be or have been restored.
-With \fB\-a\fR option, the first and second columns denote the origin and initial/new/current package name, respectively.
+With \fB\-a\fR option, the first and second columns denote the flavored origin and initial/new/current package name, respectively.
 .TP
 \fBdeleted\fR
 Leaf, obsolete or unneeded ports are to be or have been deleted.
-With \fB\-a\fR option, the first and second columns denote the origin and initial/new/current package name, respectively.
+With \fB\-a\fR option, the first and second columns denote the flavored origin and initial/new/current package name, respectively.
 .TP
 \fBconflict\fR
 Conflicting ports which are temporarily deleted.
-With \fB\-a\fR option, the first, second and third columns denote the origin, initial/new/current package name, and opponent ports concatenated by comma respectively.
+With \fB\-a\fR option, the first, second and third columns denote the flavored origin, initial/new/current package name, and opponent ports concatenated by comma respectively.
 .TP
 \fBrequirements\fR \fIglob1\fR [\fIglob2\fR ...]
 Ports required by matching ports/packages.
-With \fB\-a\fR option, the first, second, third and fourth columns denote the origin of the queried port, initial/new/current package name of the queried port, origin of a requirement of the queried port and initial/new/current package name of the requirement, respectively.
+With \fB\-a\fR option, the first, second, third and fourth columns denote the flavored origin of the queried port, initial/new/current package name of the queried port, flavored origin of a requirement of the queried port and initial/new/current package name of the requirement, respectively.
 .TP
 \fBdependents\fR \fIglob1\fR [\fIglob2\fR ...]
 Ports depending on matching ports/packages.
-With \fB\-a\fR option, the first, second, third and fourth columns denote the origin of the queried port, initial/new/current package name of the queried port, origin of a dependent of the queried port and initial/new/current package name of the dependent, respectively.
+With \fB\-a\fR option, the first, second, third and fourth columns denote the flavored origin of the queried port, initial/new/current package name of the queried port, flavored origin of a dependent of the queried port and initial/new/current package name of the dependent, respectively.
 .TP
 \fBinitrequirements\fR \fIglob1\fR [\fIglob2\fR ...]
 Ports initially required by matching initially installed ports/packages.
-With \fB\-a\fR option, the first, second, third and fourth columns denote the origin of the queried port, package name of the queried port, origin of a requirement of the queried port and package name of the requirement, respectively.
+With \fB\-a\fR option, the first, second, third and fourth columns denote the flavored origin of the queried port, package name of the queried port, flavored origin of a requirement of the queried port and package name of the requirement, respectively.
 .TP
 \fBinitdependents\fR \fIglob1\fR [\fIglob2\fR ...]
 Ports initially depending on matching initially installed ports/packages.
-With \fB\-a\fR option, the first, second, third and fourth columns denote the origin of the queried port, package name of the queried port, origin of a dependent of the queried port and package name of the dependent, respectively.
+With \fB\-a\fR option, the first, second, third and fourth columns denote the flavored origin of the queried port, package name of the queried port, flavored origin of a dependent of the queried port and package name of the dependent, respectively.
+.TP
+\fBconflict_files\fR \fIglob1\fR [\fIglob2\fR ...]
+Possible additional conflict files of matching ports/packages.
+The first and second columns denote the possible conflict package and file path, respectively.
+For officially registered conflict, nothing is outputted.
+In other words, if something is outputted, the port Makefile can have some defect or the custom modification of the system can be confusing the port or the conflicting packages.
 .TP
 \fBstatus\fR \fIglob1\fR [\fIglob2\fR ...]
 Current success/failure status in (re)installation of matching ports/packages.
-Returned values are null, "todo", "done", "resolved", "failure", "redo", "taboo", "need", "noneed", "restored", "deleted" or "conflict", where null means that they are untouched in the current option configuration or temporary reset due to configuration changes. 
+Returned values are null, "todo", "done", "resolved", "failure", "redo", "taboo", "freeze", "need", "noneed", "restored", "deleted" or "conflict", where null means that they are untouched in the current option configuration or temporary reset due to configuration changes. 
 .RE
 .SH OPTIONS
 If duplicated or conflicting ones are set, the last ones are effective.
@@ -302,6 +370,13 @@ Reset option settings for minor controls.
 Option settings for group 4 are once reset and replaced with the newly specified ones.
 Check the saved options by \fBportsreinstall options\fR command before specifying this option.
 .PD
+.IP \fB\-S\fR
+.PD 0
+.TP
+\fB\-\-no\-opening\-message\fR
+Suppress the credit and opening messages.
+Option \fB\-a\fR takes higher priority over this option.
+.PD
 .SS Group 3: Effective only with redo command
 .IP \fB\-L\fR
 .PD 0
@@ -349,7 +424,8 @@ This option affects behaviors of \fB\-t\fR, \fB\-T\fR and \fB\-q\fR options.
 .PD 0
 .TP
 \fB\-\-apply\-default\-config\fR
-The temporary database is built by skipping executing \fBmake config\fR and applying default values for unconfigured port options.
+The temporary database is built by skipping executing \fBmake config\-conditional\fR so that the port options are unchanged.
+The default values are applied to unconfigured port options.
 The port options are unchanged and unsaved (they are saved in case of old ports trees in which \fBdialog\fR(1) is used instead of \fBdialog4ports\fR(1)).
 .PD
 .IP \fB\-c\fR
@@ -380,8 +456,9 @@ Do not clean up obsolete or unused distfiles.
 .PD 0
 .TP
 \fB\-\-fetch\-only\fR
-Stop the reinstallation process for each port and continue to the next after the successful fetch and checksum of all required distfiles.
-Note that conflicting/obsolete/leaf packages will be deleted even in this mode.
+Execute fetch and checksum verification only at the (re)installation process for each port.
+Packages are also fetched if applicable.
+Regardless of this mode, missing essential tools for package management such as \fBpkg\fR(8) and \fBdialog4ports\fR(1) will be installed.
 .PD
 .IP \fB\-f\fR
 .PD 0
@@ -395,12 +472,15 @@ In this case, when a looped dependency is detected, the first found dependency w
 .PD 0
 .TP
 \fB\-\-use\-prebuilt\-package\fR
-Use prebuilt packages for ports with the default configurations, i.e., that no part option is changed from the default, no knob (make environment variable or make argument) is defined, and no replacement or update is made to required ports.
-This option is useful for new installation and will not be harmful for the most other cases.
-The actual merit of this option depends on the service levels and qualities of the remote package sites; since October 31, 2013, weekly-updated pkgng packages are provided for major OS distributions (as of November 15, 2013, i386 and amd64) until their end-of-life while legacy packages are provided only at each release timing in case of existing release versions of major architectures; the situations are different for STABLE and CURRENT versions and more various architectures are supported for legacy packages.
-The official support of legacy packages were abandoned at September 1, 2014, but third-party services might be used by configuring PACKAGECHECKSUMROOTS and PACKAGEROOTS if available somewhere.
-It is noted that this option can be inconvenient for ports whose dependencies on other packages, files or other system-specific values are automatically arranged during the build or installation processes by detection outside of control by port options, knobs or ports replacement.
+Use prebuilt packages for ports with the default configurations, i.e., in which and in the all required ports of which no port option is changed from the default and no knob (make environment variable or make argument) or replacement is defined in${LOCALBASE}/etc/portsreinstall.conf .
+As long as no knob is defined in /etc/make.conf and no environment variable has effect on package builds, this option will accelerate the (re)installtion processes without harm.
+It is noted that some ports still may be problematic with this assumption by automatic dependencies on other system configurations.
 This problem can be resolved by configuring NOPKG_* section in ${LOCALBASE}/etc/portsreinstall.conf.
+.RS
+Historical background:
+The actual merit of this option depended on the service levels and qualities of the remote package sites; since October 31, 2013, weekly-updated pkgng packages were provided for major architectures (at November 15, 2013, i386 and amd64 only) until their end-of-life while legacy packages were provided only at each release timing; the situations were different for STABLE and CURRENT versions and more various architectures were supported for legacy packages.
+The official support of legacy packages were abandoned at September 1, 2014, but third-party services might be used by configuring PACKAGECHECKSUMROOTS and PACKAGEROOTS if available somewhere.
+.RE
 .PD
 .IP \fB\-g\fR
 .PD 0
@@ -427,8 +507,8 @@ This option suppresses upgrade, deinstallation and reinstallation of the current
 .PD 0
 .TP
 \fB\-use\-legacy\-package\-for\-missing\-pkgng\fR
-If prebuilt pkgng packages are missing, use of corresponding legacy ones is attempted instead by converting them to pkgng using \fBpkg2ng\fR.
-This option is effective only when \fB\-G\fR option is enabled and pkgng is employed for the current packages system, but will not be harmful even in the other cases.
+If prebuilt modern-style packages are missing, use of corresponding legacy ones is attempted instead by converting them to the modern-style using \fBpkg2ng\fR.
+This option is effective only when \fB\-G\fR option is enabled and the modern-style is employed for the current packages system, but will not be harmful even in the other cases.
 .PD
 .IP \fB\-n\fR
 .PD 0
@@ -568,7 +648,7 @@ Nevertheless, the all functionalities of this utility is applicable to any situa
 In a standard case, the entire reinstallation will proceed in the following step:
 .TP
 1.
-Update the ports tree and (in case of pkgng) the pkgng repository catalog;
+Update the ports tree and (except in case of the legacy package system) the \fBpkg\fR(8) repository catalog;
 .PD
 .TP
 2.
@@ -592,15 +672,15 @@ Execute the actual (re/de)installation (\fBdo\fR run);
 .PD
 .TP
 7.
-If some ports failed, retry the (re/de)installation for the failed ones and their dependents (\fBredo\fR run);
+If some ports failed, attempt manual troubleshooting by make modification to the temporary database or manually re/de-install packages in concern (\fBok\fR, \fBtaboo\fR, \fBfreeze\fR, \fBnoneed\fR, \fBreconf\fR, etc.).
 .PD
 .TP
 8.
-Make modification to the temporary database or manually re/de-install packages in concern (\fBok\fR, \fBtaboo\fR, \fBnoneed\fR, etc.).
+Execute the retrial of the (re/de)installation (\fBredo\fR run);
 .PD
 .TP
 9.
-Repeat from 6 to 7 until the all available ports succeed.
+Repeat from 7 to 8 until the all available ports succeed.
 .PD
 .PP
 A typical instance of actually executed commands for upgrading packages will be in the following flow:
@@ -612,7 +692,7 @@ A typical instance of actually executed commands for upgrading packages will be
 2.
 .B pkg update
 .RS
-(In case of pkgng)
+(No need for the legacy packages system)
 .RE
 .PD
 .TP
@@ -631,28 +711,21 @@ A typical instance of actually executed commands for upgrading packages will be
 .PD
 .TP
 5.
-.B portsreinstall redo
-.RS
-(Possibly end up with some failed ports)
-.RE
-.PD
-.TP
-6.
  ... Countermeasure to failures ...
 .PD
 .TP
-7.
+6.
 .B portsreinstall redo
 .RS
 (Possibly end up with some failed ports)
 .RE
 .PD
 .TP
-8.
- ... Repetition from 7 to 8 ...
+7.
+ ... Repetition from 6 to 7 ...
 .PD
 .TP
-9.
+8.
 .B portsreinstall redo
 .RS
 (All available ports succeed)
@@ -734,10 +807,57 @@ Then following execution of
 .B portsreinstall
 .RE
 deinstalls newly selected packages and restores unselected ones.
+.SS Package build in a chroot system
+For smooth and safe on-the-fly port upgrading, the pakage build can be carried out in a \fBchroot\fR(8) system using \fBportsreinstall-chroot\fR(8). Refer to its manual page for the detail.
+.SS Port upgrading of a cluster system
+In a cluster system where multiple nodes have the same software configuration, packages built in one node can be used for upgrading ports in the others.
+The conventional flow will be as follows:
+.PP
+1. Share file systems for /usr/ports/packages and /home among the nodes by NFS. Here we assume that the mount points are the same among the all nodes and user "admin" is used for the system administration.
+.PP
+2. In the builder node, update the ports tree and the package repository catalog.
+.RS
+root@[builder.cluster.intranet]
+.B portsnap fetch update
+.RE
+.RS
+root@[builder.cluster.intranet]
+.B pkg update
+.RE
+3. Upgrade the all pakages completely by \fBportsreinstall\fR (the command line options are just an example).
+.RS
+root@[builder.cluster.intranet]
+.B portsreinstall -qC
+.RE
+4. Create the packages and dispatching script set. This process can be skipped when \fBportsreinstall-chroot\fR(8) was used in the previous stage.
+.RS
+root@[builder.cluster.intranet]
+.B portsreinstall packupgrade create
+.RE
+5. Crop and extract the archive of the created dispatching script set.
+.RS
+root@[builder.cluster.intranet]
+.B portsreinstall packupgrade crop /home/admin/portsreinstall-upgrade.tar.gz
+.RE
+.RS
+root@[builder.cluster.intranet]
+.B rm -rf /home/admin/portsreinstall-upgrade
+.RE
+.RS
+root@[builder.cluster.intranet]
+.B mkdir -p /home/admin/portsreinstall-upgrade
+.RE
+.RS
+root@[builder.cluster.intranet]
+.B tar xzf /home/admin/portsreinstall-upgrade.tar.gz -C /home/admin/portsreinstall-upgrade
+.RE
+6. Execute the dispatched script at each target node.
+.RS
+.B ssh -l admin target01.cluster.intranet sudo /home/admin/portsreinstall-upgrade/portsreinstall-upgrade.sh
+.RE
 .SS Workaround for failed ports: conflicts: case 1
 This utility automatically resolves conflicts between ports/packages by temporary deinstallation during concerned build or installation processes according to CONFLICTS, CONFLICTS_BUILD and CONFLICTS_INSTALL defined by each port.
 This means that ports lacking proper CONFLICTS, CONFLICTS_BUILD and CONFLICTS_INSTALL definitions may undergo failures.
-Some of the undeclared conflicts may be resolved by simple redo runs.
 .PP
 Some problems may be due to coexistence of the same or related software of different versions of the requirements or the unsuccessful ports themselves.
 For analysis of the upgraded and initial requirements,
@@ -834,7 +954,7 @@ If any change was made here, execute
 .RE
 for retrial of (re)installation.
 .SS Workaround for failed ports: reconfiguration of knobs
-If the problems may be resolved by reconfiguration of the knobs, first edit the configuration file ${LOCALBASE}/etc/portsreinstall.conf so as to redefine the corresponding MARG_*, MENV_*, BEFOREBUILD_*, BEFOREDEINSTALL_* or AFTERINSTALL_* values.
+If the problems may be resolved by reconfiguration of the knobs, first edit the configuration file ${LOCALBASE}/etc/portsreinstall.conf so as to redefine the corresponding CONFLICT_*, MARG_*, MENV_*, BEFOREBUILD_*, BEFOREDEINSTALL_* or AFTERINSTALL_* values.
 If \fBportupgrade\fR(1) is installed, the corresponding configuration should be made in MAKE_ARGS, MAKE_ENV, BEFOREBUILD, BEFOREDEINSTALL or AFTERINSTALL section of \fBpkgtools.conf\fR(5).
 .PP
 Then execute
@@ -851,15 +971,15 @@ In this case, execute
 .RS
 .B portsnap fetch update
 .RE
-and, in case of pkgng, followed by
+and, followed by
 .RS
 .B pkg update
 .RE
 and then
 .RS
-.B portsreinstall reset keepopts
+.B portsreinstall reset keepstatus
 .RE
-to clean everything but the option settings and information of the initially installed packages.
+to clean everything but the option settings, information of the initially installed packages and the progress of unchanged successful ports.
 Then execute
 .RS
 .B portsreinstall
@@ -946,16 +1066,47 @@ Configuration file of \fBportupgrade\fR(1).
 .SH HISTORY
 \fBportsreinstall\fR has been developed as below.
 .TP
-3.3.3 (22 May 2017)
+4.0.0 (?? June 2018)
 .RS
-[NEW] Option \-F is added.
+[NEW] Flavor is supported. Related to this feature, representations of port origins without flavor is recognized to exactly match the unflavored ones.
+.PP
+[NEW] Option \fB\-F\fR is added.
+.PP
+[NEW] \fBpackupgrade\fR command is added.
+.PP
+[NEW] \fBreset keepstatus\fR command is added.
+.PP
+[NEW] \fBfreeze\fR and \fBshow freeze\fR commands are added. FREEZE section is added to ${LOCALBASE}/etc/portsreinstall.conf.
+.PP
+[NEW] \fBshow conflict_files\fR\fR command is added.
+.PP
+[NEW] CONFLICT section is added to ${LOCALBASE}/etc/portsreinstall.conf.
 .PP
-[BUG FIX] pkgsanity command had lost its ability to detect missing files because of the specification change of pkg(8).
+[NEW] Utilities of \fBportsreinstall-upgrade\fR(8) and \fBportsreinstall-chroot\fR(8) are added.
+.PP
+[NEW] Change of port options made outside of \fBportsreinstall\fR(8) is automatically detected.
+.PP
+[IMPROVED] The (re)installation process is changed to be repeated until all-automatically resolvable problems are resolved. Thus there is no more need to simply repeat \fBredo\fR command to complete the automatic solution.
+.PP
+[IMPROVED] The way of detecting the packages system is changed to check both WITH_PKG and WITH_PKGNG in accordance with the specification change of the ports tree. The descriptions about the packages system is updated as well.
+.PP
+[IMPROVED] \fBreset\fR command is improved to reset the database cleaner and preserve manually set taboo/freeze/need/noneed lists.
+.PP
+[IMPROVED] \fBreconf\fR command is changed to be available any time.
+.PP
+[IMPROVED] Inspection of merged ports is improved to make the deinstallation of old packages effective.
+.PP
+[BUG FIX] \fBpkgsanity\fR command had lost its ability to detect missing files because of the specification change of \fBpkg\fR(8).
+.PP
+[BUG FIX] Command line arguments could have interpreted "add" keyword as a glog matching math/add.
+.PP
+[BUG FIX] Option \fB\-k\fR did not work properly with option \fB\-g\fR.
 .RE
 .TP
 3.3.2 (15 February 2017)
 .RS
-[CHANGED] The permission of the configuration sample file is changed to writable so that pkg(8) will install the configuration file to be writable.
+.PP
+[CHANGED] The permission of the configuration sample file is changed to writable so that \fBpkg\fR(8) will install the configuration file to be writable.
 .PP
 [BUG FIX] "Selection of removing leaf ports" might have failed at ports which has not been installed yet and becomes leaves by REPLACE_* tags in the configuration file.
 .RE
@@ -973,9 +1124,9 @@ Configuration file of \fBportupgrade\fR(1).
 .PP
 [IMPROVED] Automatic workaround of looped dependencies is implemented at the phase of "Completion of *-time requirement lists" in the preparation stage.
 .PP
-[CHANGED] Dependencies on pkg(8) is changed to be ignored.
+[CHANGED] Dependencies on \fBpkg\fR(8) is changed to be ignored.
 .PP
-[BUG FIX] The rescue process for cases missing pkg(8) was not working well.
+[BUG FIX] The rescue process for cases missing \fBpkg\fR(8) was not working well.
 .PP
 [BUG FIX] The phase of "Completion of *-time requirement lists" in the preparation stage was caught into an infinite loop when looped dependencies exist.
 .PP
@@ -995,7 +1146,7 @@ Configuration file of \fBportupgrade\fR(1).
 .PP
 [IMPROVED] Support for cases that alternative version of ports\-mgmt/pkg (ports\-mgmt/pkg\-devel, switched by defining WITH_PKG=devel in /etc/make.conf) or ports-mgmt/dialog4ports (DIALOGPORT=\fIport_origin\fR in /etc/make.conf, reserved for the future) is used are implemented.
 .PP
-[BUG FIX] Reinstallation of pkg(8) could encounter error termination.
+[BUG FIX] Reinstallation of \fBpkg\fR(8) could encounter error termination.
 .RE
 .TP
 3.1.1 (17 December 2014)
@@ -1150,6 +1301,8 @@ and select "y" in the queries for spoiled packages.
 [BUG FIX] Reinstallation processes were unintentionally terminated when the backup package creation was unsuccessful.
 .PP
 [BUG FIX] Options \fB\-O\fR, \fB\-T\fR and \fB\-t\fR did not work for once-succeeded ports.
+.PP
+[BUG FIX] Detection of conflict was overestimated for some ports.
 .RE
 .TP
 3.0.0 (01 June 2013)
@@ -1435,31 +1588,43 @@ In order to choose pkgng in systems from 800505 (just before 8.1-RELEASE) to jus
 .RS
 .B WITH_PKGNG=yes
 .RE
+.RS
+or
+.RE
+.RS
+.B WITH_PKG=yes
+.RE
 in /etc/make.conf.
 .PP
 In order to choose the legacy one in systems of 1000017 (10-CURRENT) or later, put
 .RS
 .B WITHOUT_PKGNG=yes
 .RE
+.RS
+or
+.RE
+.RS
+.B WITHOUT_PKG=yes
+.RE
 in /etc/make.conf.
 .SH "SEE ALSO"
-\fBpkg_add\fR(1),
-\fBpkg_create\fR(1),
-\fBpkg_delete\fR(1),
 \fBpkg_glob\fR(1),
 \fBportupgrade\fR(1),
 \fBportsdb\fR(1),
 \fBports_glob\fR(1),
 \fBpkgtools.conf\fR(5),
 \fBports\fR(7),
-\fBpkg-add\fR(8),
-\fBpkg-create\fR(8),
-\fBpkg-delete\fR(8),
+\fBpkg\-add\fR(8),
+\fBpkg\-create\fR(8),
+\fBpkg\-delete\fR(8),
 \fBportmaster\fR(8)
+\fBportsreinstall\-chroot\fR(8),
+\fBportsreinstall\-chroot\-mount\fR(8),
+\fBportsreinstall\-upgrade\fR(8),
 .SH COPYRIGHT
 This software is distributed under the 2-Clause BSD License.
 .PP
-(C)\ 2010\-2014\ Mamoru\ Sakaue,\ MwGhennndo,\ All\ Rights\ Reserved.
+(C)\ 2010\-2018\ Mamoru\ Sakaue,\ MwGhennndo,\ All\ Rights\ Reserved.
 .PP
 Email:\ sakaue.mamoru@samurai.mwghennn.net
 .PP
diff --git a/share/bin/portsreinstall-chroot-mount b/share/bin/portsreinstall-chroot-mount
new file mode 100755 (executable)
index 0000000..72f7c42
--- /dev/null
@@ -0,0 +1,90 @@
+#!/bin/sh -e
+# ==================================================================================
+# portsreinstall chroot main script
+# Copyright (C) 2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# This software is distributed under the 2-Clause BSD License.
+# ==================================================================================
+
+# ==================================================
+# ================== ENVIRONMENT ===================
+# ==================================================
+
+# ============ Set up of environment =============
+PROGRAM=portsreinstall
+APPNAME=`basename "$0"`
+
+MYPREFIX=`realpath "\`dirname \"$0\"\`"/../../..`
+LIBDIR=${MYPREFIX}/lib/${PROGRAM}
+LIBEXECDIR=${MYPREFIX}/libexec/${PROGRAM}
+SHAREDIR=${MYPREFIX}/share/${PROGRAM}
+ETCDIR=${MYPREFIX}/etc
+
+. ${LIBDIR}/libcommand.sh
+. ${LIBDIR}/libcommand_do.sh
+. ${LIBDIR}/libcommand_flexconf.sh
+. ${LIBDIR}/libcommand_forget.sh
+. ${LIBDIR}/libcommand_pkgs.sh
+. ${LIBDIR}/libcommand_show.sh
+. ${LIBDIR}/libconf.sh
+. ${LIBDIR}/libdatabase_build.sh
+. ${LIBDIR}/libdatabase_maintain.sh
+. ${LIBDIR}/libdatabase_query.sh
+. ${LIBDIR}/libdatabase_record.sh
+. ${LIBDIR}/libdeinstall.sh
+. ${LIBDIR}/libfileedit.sh
+. ${LIBDIR}/libmain.sh
+. ${LIBDIR}/libmessage.sh
+. ${LIBDIR}/libmisc.sh
+. ${LIBDIR}/liboptions.sh
+. ${LIBDIR}/libpkgsys.sh
+. ${LIBDIR}/libprogram.sh
+. ${LIBDIR}/libreinstall.sh
+. ${LIBDIR}/libstr.sh
+. ${LIBDIR}/libtemp.sh
+. ${LIBDIR}/libusage.sh
+
+. ${LIBDIR}/chroot/libfs.sh
+
+. ${LIBDIR}/chroot-mount/libcommand.sh
+. ${LIBDIR}/chroot-mount/libconf.sh
+. ${LIBDIR}/chroot-mount/libdatabase_maintain.sh
+. ${LIBDIR}/chroot-mount/libmain.sh
+. ${LIBDIR}/chroot-mount/libmessage.sh
+. ${LIBDIR}/chroot-mount/liboptions.sh
+. ${LIBDIR}/chroot-mount/libtemp.sh
+. ${LIBDIR}/chroot-mount/libusage.sh
+
+[ -n "${SYSTEMBASE}" ] || SYSTEMBASE=`realpath "${MYPREFIX}"/../..`
+DBDIR=${SYSTEMBASE}/var/tmp/${PROGRAM}-chroot.db
+
+main_set_version
+misc_init_vardefs
+temp_trap_init
+main_load_conf
+
+# ==================================================
+# ========= PARSING OPTIONS AND ARGUMENTS ==========
+# ==================================================
+
+main_parse_options_arguments "$@"
+opt_invalidate_mount_privilege=no
+
+# ========================================================
+# ================== SET UP OF PARAMETERS ==================
+# ========================================================
+
+# Termination messages during construction of the temporary database
+temp_setup_terminate_process
+
+# Opening title
+message_credit
+message_echo
+
+# Check of the mounting/unmounting privilege of the environment
+main_check_of_mounting_unmounting_privilege
+
+# ==================================================
+# ====================== MAIN =======================
+# ==================================================
+
+command_all_exec_without_pkgtools "$@"
diff --git a/share/bin/portsreinstall-upgrade b/share/bin/portsreinstall-upgrade
new file mode 100644 (file)
index 0000000..7c4735f
--- /dev/null
@@ -0,0 +1,82 @@
+#!/bin/sh -e
+# ==================================================================================
+# portsreinstall upgrade main script
+# Copyright (C) 2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# This software is distributed under the 2-Clause BSD License.
+# ==================================================================================
+
+# ==================================================
+# ================== ENVIRONMENT ===================
+# ==================================================
+
+# ============ Set up of environment =============
+PROGRAM=portsreinstall
+APPNAME=`basename "$0"`
+
+MYPREFIX=`dirname "\`realpath $0\`"`
+LIBDIR=${MYPREFIX}/lib
+LIBEXECDIR=${MYPREFIX}/libexec/${PROGRAM}
+ETCDIR=${MYPREFIX}/etc
+
+. ${LIBDIR}/libcommand.sh
+. ${LIBDIR}/libcommand_do.sh
+. ${LIBDIR}/libcommand_flexconf.sh
+. ${LIBDIR}/libcommand_forget.sh
+. ${LIBDIR}/libcommand_pkgs.sh
+. ${LIBDIR}/libcommand_show.sh
+. ${LIBDIR}/libconf.sh
+. ${LIBDIR}/libdatabase_build.sh
+. ${LIBDIR}/libdatabase_maintain.sh
+. ${LIBDIR}/libdatabase_query.sh
+. ${LIBDIR}/libdatabase_record.sh
+. ${LIBDIR}/libdeinstall.sh
+. ${LIBDIR}/libfileedit.sh
+. ${LIBDIR}/libmain.sh
+. ${LIBDIR}/libmessage.sh
+. ${LIBDIR}/libmisc.sh
+. ${LIBDIR}/liboptions.sh
+. ${LIBDIR}/libpkgsys.sh
+. ${LIBDIR}/libprogram.sh
+. ${LIBDIR}/libreinstall.sh
+. ${LIBDIR}/libstr.sh
+. ${LIBDIR}/libtemp.sh
+. ${LIBDIR}/libusage.sh
+
+. ${LIBDIR}/upgrade/libcommand.sh
+. ${LIBDIR}/upgrade/libcommand_do.sh
+. ${LIBDIR}/upgrade/libmain.sh
+. ${LIBDIR}/upgrade/libmessage.sh
+. ${LIBDIR}/upgrade/liboptions.sh
+. ${LIBDIR}/upgrade/libusage.sh
+
+DBDIR=/var/tmp/${APPNAME}.db
+SAVEDENV=${ETCDIR}/setenv.sh
+SAVEDCONF=${ETCDIR}/complete_setup.sh
+
+main_set_version
+misc_init_vardefs
+temp_trap_init
+
+. "${SAVEDENV}"
+
+# ==================================================
+# ========= PARSING OPTIONS AND ARGUMENTS ==========
+# ==================================================
+
+main_parse_options_arguments "$@"
+
+# ========================================================
+# ================== SET UP OF PARAMETERS ==================
+# ========================================================
+
+main_setup_parameters "$@"
+
+# ==================================================
+# ====================== MAIN =======================
+# ==================================================
+
+# Execute command operations which must be done before the main process
+command_all_exec_before_main "$@"
+
+# Execute command operations as the main process
+command_all_exec_main "$@"