OSDN Git Service

[NEW] Option of -g is added.
[portsreinstall/current.git] / portsreinstall
1 #!/bin/sh -e
2 # ==================================================================================
3 # portsreinstall main script
4 # Copyright (C) 2010-2013 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
5 # This software is distributed under the 2-Clause BSD License.
6 # ==================================================================================
7
8 # ================================================
9 # ================ PREPARATION ===================
10 # ================================================
11
12 APPNAME=`basename "$0"`
13 MYVERSION=2.2.2+toward_2.2.3_20130119200821
14
15 PREFIX=${PREFIX:-/usr/local}
16 CONFFILE=${PREFIX}/etc/${APPNAME}.conf
17 DBDIR=/var/tmp/${APPNAME}.db
18 PKGTOOLSCONF=${PREFIX}/etc/pkgtools.conf
19
20 # ============= Creation of temporary work directories =============
21 terminate_process ()
22 {
23 }
24 warn_update_ports ()
25 {
26 }
27 trap 'errno=$?; warn_update_ports; terminate_process; rm -rf "${TMPDIR}" 2> /dev/null; [ $errno -gt 0 -a $errno -ne 130 ] && echo "(Error exit by $errno)" >&2; exit $errno' 0 1 2 3 9 15 17 18
28 { until TMPDIR=`mktemp -dq /tmp/"${APPNAME}".XXXXXXXX` ; do : ; done ; }
29 chgrp "`id -gn`" "${TMPDIR}"
30
31 # ============= Save arguments for updated restart =============
32 restart_command ()
33 {
34         echo -n "exec `echo "$0" | sed -E 's/(.)/\\\\\\1/g'`"
35         while [ $# -ge 1 ]
36         do
37                 echo -n " `echo "$1" | sed -E 's/(.)/\\\\\\1/g'`"
38                 shift
39         done
40 }
41 restart_command "$@" > ${TMPDIR}/restart_command.sh
42
43 # ============= Option check =============
44 help_mode=0
45 option_err=0
46 target_dependent_ports=
47 target_required_ports=
48 target_dependent_ports_form2=
49 target_required_ports_form2=
50 taboo_ports=
51 taboo_ports_form2=
52 load_pkgtoolsconf=undef
53 show_version=no
54 avoid_vulner=no
55 skip_unchanged=no
56 keep_distfiles=no
57 renew_options=no
58 supress_self_upadte=no
59 supress_pkgng_upadte=no
60 supress_obsolete_db_clean=no
61 while :
62 do
63         if [ "$1" = "-h" ]
64         then
65                 help_mode=1
66                 shift
67         elif [ "$1" = "-H" ]
68         then
69                 help_mode=2
70                 shift
71         elif [ "$1" = "-t" ]
72         then
73                 target_dependent_ports=$target_dependent_ports,$2
74                 shift 2
75         elif [ "$1" = "-T" ]
76         then
77                 target_required_ports=$target_required_ports,$2
78                 shift 2
79         elif [ "$1" = "-r" ]
80         then
81                 target_dependent_ports_form2="$target_dependent_ports_form2 $2"
82                 shift 2
83         elif [ "$1" = "-R" ]
84         then
85                 target_required_ports_form2="$target_required_ports_form2 $2"
86                 shift 2
87         elif [ "$1" = "-x" ]
88         then
89                 taboo_ports=$taboo_ports,$2
90                 shift 2
91         elif [ "$1" = "-X" ]
92         then
93                 taboo_ports_form2="$taboo_ports_form2 $2"
94                 shift 2
95         elif [ "$1" = "-p" ]
96         then
97                 load_pkgtoolsconf=default
98                 shift
99         elif [ "$1" = "-P" ]
100         then
101                 load_pkgtoolsconf=override
102                 shift
103         elif [ "$1" = "-Q" ]
104         then
105                 load_pkgtoolsconf=no
106                 shift
107         elif [ "$1" = "-V" ]
108         then
109                 show_version=yes
110                 shift
111         elif [ "$1" = "-s" ]
112         then
113                 avoid_vulner=yes
114                 shift
115         elif [ "$1" = "-q" ]
116         then
117                 skip_unchanged=yes
118                 shift
119         elif [ "$1" = "-d" ]
120         then
121                 keep_distfiles=yes
122                 shift
123         elif [ "$1" = "-N" ]
124         then
125                 renew_options=yes
126                 shift
127         elif [ "$1" = "-k" ]
128         then
129                 supress_self_upadte=yes
130                 shift
131         elif [ "$1" = "-g" ]
132         then
133                 supress_pkgng_upadte=yes
134                 shift
135         elif [ "$1" = "-c" ]
136         then
137                 supress_obsolete_db_clean=yes
138                 shift
139         else
140                 break
141         fi
142 done
143
144 if [ $help_mode -ne 0 ]
145 then
146 #       if [ $# -gt 0 ]
147 #       then
148 #               option_err=1
149 #       fi
150 fi
151
152 credit ()
153 {
154         fold -s >&2 << eof
155 ${APPNAME} version ${MYVERSION}
156  -- Ports upgrading utility for massive forced reinstallation
157  -- And for those who are pursuing the perfect packages environment
158 Copyright (C) 2010 - 2013 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
159 Email: <sakaue.mamoru@samurai.mwghennn.net>
160 Homepage: <http://www.mwghennndo.com/softwares/portsreinstall/>
161 eof
162 }
163
164 # Usage
165 if [ $help_mode -eq 1 -o $option_err -eq 1 ]
166 then
167         fold -s << eof
168 USAGE: ${APPNAME} [OPTIONS] [command]
169
170 [OPTIONS]
171  -h : Show this short help.
172  -H : Show long help.
173  -V : Show the current version.
174  -t glob1[,glob2,...] : Reinstall only target ports and their dependents.
175  -r glob : Reinstall only the target port and their dependents.
176  -T glob1[,glob2,...] : Reinstall only target ports and their requirements.
177  -R glob : Reinstall only target ports and their requirements.
178  -x glob1[,glob2,...] : Set the port glob(s) to be taboo.
179  -X glob : Set a port glob to be taboo.
180  -p : Import settings from pkgtools.conf(5) as the primary if exists (default).
181  -P : Import settings from pkgtools.conf(5) as the secondary if exists.
182  -Q : Ignore pkgtools.conf(5) even if it exists.
183  -s : Build of vulnerable ports are avoided by triggering errors.
184  -q : Ports whose all requirements and themselves are not new are skipped.
185  -d : Do not clean up obsolete or unused distfiles.
186  -N : Renew option settings (only for redo command).
187  -k : Keep ${APPNAME} itself untouched.
188  -g : Keep ports-mgmt/pkg untouched.
189  -c : Suppress cleaning the temporal database even if its obsolete.
190
191 [ARGUMENTS]
192  command: do (default) | prepare | redo | clean | ok add globs...
193           | ok del globs... | taboo add globs... | taboo del globs...
194           | save [dir] | load path
195           | show todo | show done | show resolved | show failure | show redo
196           | show pending | show taboo | show deleted
197           | show requirements glob... | show dependents glob...
198
199 [DESCRIPTIONS]
200  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.
201  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.
202 eof
203         exit $option_err
204 elif [ $help_mode -eq 2 ]
205 then
206         credit
207         fold -s << eof
208
209 USAGE: ${APPNAME} [OPTIONS] [command]
210
211 [OPTIONS]
212  -h : Show short help.
213  -H : Show this long help.
214  -V : Show the current version.
215  -t glob1[,glob2,...] : Reinstall only target ports and their dependents.
216         Target ports which are not installed yet are newly installed.
217         Target ports which are obsolete are deinstalled.
218         This option can be given multiply.
219         This option is recognized in the first "do" or "redo" runs, and
220         transferred to the restarted runs.
221         Dependency relations are inspected for all installed packages as well.
222         Combination with options "-T", "-r" and "-R" is available.
223  -r glob : Reinstall only the target port and their dependents.
224         This option can be given multiply.
225         The difference from "-t" is that only one port glob can be specified.
226         Thus a package name with commas is available.
227         Combination with options "-t", "-T" and "-R" is available.
228  -T glob1[,glob2,...] : Reinstall only target ports and their requirements.
229         Target ports which are not installed yet are newly installed.
230         Target ports which are obsolete are deinstalled.
231         This option can be given multiply.
232         This option is recognized in the first "do" or "redo" runs, and
233         transferred to the restarted runs.
234         Dependency relations are inspected for all installed packages as well.
235         Combination with options "-t", "-r" and "-R" is available.
236  -R glob : Reinstall only target ports and their requirements.
237         This option can be given multiply.
238         The difference from "-T" is that only one port glob can be specified.
239         Thus a package name with commas is available.
240         Combination with options "-t", "-r" and "-T" is available.
241  -x glob1[,glob2,...] : Set the port glob(s) to be taboo.
242         This option registers a port to be ignored as taboo.
243         This option can be given multiply.
244         Mainly for ports that show terrible behaviors resulting in system crash.
245         This option is recognized in the first "do" or "redo" runs, and
246         transferred to the restarted runs.
247         Alternatively you can do the same thing by "taboo" command.
248         If you want to register permanently, set to the configuration file.
249         Combination with options "-X" is available.
250  -X glob : Set a port glob to be taboo.
251         This option can be given multiply.
252         The difference from "-x" is that only one port glob can be specified.
253         Thus a package name with commas is available.
254         Combination with options "-x" is available.
255  -p : Import settings from pkgtools.conf(5) as the primary.
256         For duplicated configurations, values in pkgtools.conf are applied
257         first and then those in ${APPNAME}.conf are.
258         This option is ignored when you restart a terminated process.
259         (Default; ignored if ports-mgmt/portupgrade* is not installed)
260  -P : Import settings from pkgtools.conf(5) as the secondary.
261         For duplicated configurations, values in ${APPNAME}.conf are applied
262         first and then those in pkgtools.conf are.
263         This option is ignored when you restart a terminated process.
264         (Ignored if ports-mgmt/portupgrade* is not installed)
265  -Q : Ignore pkgtools.conf(5) even if it exists.
266         This option is ignored when you restart a terminated process.
267  -s : Build of vulnerable ports are avoided by triggering errors.
268         Note that already installed vulnerable packages are untouched.
269         If you desire to uninstall them, do it manually.
270         This specification will be reasonable for the practical situations.
271         This option is fixed at the first "do" run, and transferred to the
272         following runs.
273         If you want to continue the reinstallation process by resetting
274         this option, execute by "redo" command with "-N" option.
275  -q : Ports whose all requirements and themselves are not new are skipped.
276         This option is safe and useful when the all of the major version of
277         the system, configuration options of each ports, pkgtools.conf(5),
278         ${APPNAME}.conf are unchanged.
279         This option is fixed at the first "do" run, and transferred to the
280         following runs.
281         If you want to continue the reinstallation process by resetting
282         this option, execute by "redo" command with "-N" option.
283  -d : Do not clean up obsolete or unused distfiles.
284         This option is fixed at the first "do" run, and transferred to the
285         following runs.
286         If you want to continue the reinstallation process by resetting
287         this option, execute by "redo" command with "-N" option.
288  -N : Renew option settings.
289         This option is effective only with "redo" command.
290         Option settings for "-s", "-q" and "-d" are reset according to
291         the simultaneously given ones.
292  -k : Keep ${APPNAME} itself untouched.
293         This option supresses update, deinstallation and reinstallation of
294         the currently installed ${APPNAME}.
295  -g : Keep ports-mgmt/pkg untouched.
296         This option supresses update, deinstallation and reinstallation of
297         the currently installed ports-mgmt/pkg (pkgng).
298  -c : Suppress cleaning the temporal database even if its obsolete.
299         By default, the temporal database is automatically cleaned up if
300         it is older than the ports tree or ${APPNAME} itself is to be
301         updated.
302         This option replace this behavior with termination with warnings.
303         This option should not be used unless the user has special
304         intentions.
305
306 [ARGUMENTS]
307  command: (For optional operations or confirmation)
308       {one of the following commands}
309       do : full execution (default)
310       prepare : stop before the actual operations to the ports/packages
311       redo : execute again for failed ports and their dependents
312       clean : clean up the temporal database
313       ok add glob1 [glob2 ...] : register manually resolved ports
314       ok del glob1 [glob2 ...] : deregister manually resolved ports
315       taboo add glob1 [glob2 ...]: register taboo ports
316       taboo del glob1 [glob2 ...]: deregister taboo ports
317       save [dir] : save the current temporal database as a .tar.gz archive
318       load path : load a temporal database archive
319       show [args] : show the list of ports to be reinstalled
320             todo : ports to be reinstalled in the current do/redo process (default)
321             done : already reinstalled ports
322             resolved : manually reinstalled ports
323             failure : failed ports
324             redo : ports succeeded once but to be reinstalled in the next redo process
325             pending : ports to be reinstalled after success in their requirements
326             taboo : taboo ports
327             deleted : obsolete ports to be or have been deleted
328             requirements glob1 [glob2 ...] : ports required by matching ports
329             dependents glob1 [glob2 ...] : ports depending on matching ports
330
331 [CONFIGURATION FILE]
332           ${CONFFILE}
333
334 [NOTATIONS]
335  The "glob" is either of pkgname_glob or portorigin_glob explained in the man page of portsdb(1) and ports_glob(1): for example, zip-3.0, zip-*, and archivers /zip. Here the wild card symbol "*" must be quoted or escaped. In evaluation of globs, ports_glob(1) is used if it is installed for better compatibility, otherwise an alternative internal function is used.
336
337 [DESCRIPTIONS]
338  This utility realizes smart reinstallation of a large number of ports by allowing you to run when when the machine is free and terminate when busy.
339  Concretely, you can stop the process by CTRL+C anytime and restart quickly.
340  This functionality allows you, for example, to start this utility before lunch, terminate after lunch, restart before dinner, terminate after dinner, restart before going to bed, terminate after breakfast, restart before lunch, ..., and finally complete.
341
342  The policy of this utility is to complete the job by the most automatic and finally successful way even if it will take a long time in total.
343  All missing build- and run-time dependencies are newly installed if any.
344  All reinstallation processes are tried to be proceeded forcibly by ignoring errors or vulnerabilities as possible.
345  This utility pursues the consistency of the dependency relations in the latest version of the ports tree by on-the-fly entire reconstruction of the relations while portupgrade(1) and portmaster(8) believe the existing relations of the installed packages to reduce the total work time as much as possible.
346
347  In the simplest case, all a user has to do toward complete reinstallation is execute this utility without any arguments (corresponding to "do" command). If the run completes with notations on failures for any ports, after resolving the errors manually, register the resolved ports by executing this utility with "ok add" command and then execute with "redo" command. This task is continued until successful completion.
348
349  The algorithms of this utility are customized for massive reinstallation to be invoked after major upgrade of the system where rebuild of all third-party applications are encouraged before cleaning up obsolete system libraries.
350  Nevertheless, the all functionalities of this utility is applicable to any situations where complete reinstallation of the all or parts of ports is preferred, e.g., when you have been lazy in upgrade of ports for too long time.
351  For the usual purposes of upgrading packages installed by ports, you are recommended to use ports-mgmt/portupgrade or ports-mgmt/portmaster instead.
352
353  If this utility has been installed by ports/packages and the corresponding port is renewed, update of this utility is carried out first and then the following processes are continued by the new version after cleaning up the temporal database.
354
355  The scheme of this utility is divided into the temporal database construction phase and the reinstallation phase.
356  Execution by "portsreinstall prepare" procedes to the end the first phase, and that without any argument procedes to the end of the second phase.
357  Each of these two major phases is divided into minor phases.
358  When the previously terminated process is restarted, completed minor phases are skipped.
359
360  The massive minor phases belong to "collecting dependencies of installed/ missing packages", "ordering dependencies" for the first major phase and "reinstallation" "package database update" for the second.
361  Most of them are divided into more minor phases except for "package database update".
362
363  When option(s) "-t", "-r", "-T"  or "-R" is/are given in the first run of "do" or "redo" commands, only the targets and their required or dependent ports are reinstalled (or deleted if obsolete).
364  This specification is effective until the completion of the run.
365  Run by "redo" command without the options inherits the previous settings.
366  Meanwhile, run by "redo" command with the options resets the previous settings, and inspects the dependencies again if new ports are to be installed.
367
368  The user is encouraged to run this utility under script(1) so as to record all logs in order to resolve problems that you may (rather "will", practically) encounter.
369  The solutions depend on the individual cases.
370  If the problem will be resolved by reconfiguration of the port option, execute "make config" at the corresponding port directory, and then restart this utility.
371  If the problem will be resolved by manual fetch of tarballs, do it and then restart this utility.
372  If the problem will be resolved by deleting a concerned package, do it by "pkg_delete -f {package}" (conventional package), "pkg delete -f {package}" (new generation package, pkgng) or execute "make deinstall" at the corresponding port directory, then execute "${APPNAME} ok add \$glob" where "\$glob" is the ports glob of the concerned port, and then restart this utility.
373  If the problem will be resolved by manual reinstallation using pkg_add(1) (conventional package), pkg add (pkg-add(8), pkgng) or so on, do it and glob of execute "${APPNAME} ok add \$glob" where "\$glob" is the ports the concerned port, and then restart this utility by "redo" command.
374
375  The current package system is automatically detected; the new generation package (pkgng) is used if "WITH_PKGNG=yes" is set and "WITHOUT_PKGNG=yes" is not set /etc/make.conf, and otherwise the conventional package is used.
376
377  If you are familiar to the mechanism of Ports Collections system, in order to minimize package conflictions, it may be a good idea to delete packages which you don't think necessary before starting to use this utility. Don't be afraid to delete necessary dependencies because all required ports are automatically installed.
378
379  If you run into confusion, it may be a good idea to clean up the temporal database by executing "${APPNAME} clean" and start again from the first.
380 ================================================================================
381 eof
382         exit
383 fi
384
385 if [ $show_version = yes ]
386 then
387         echo "${APPNAME} version ${MYVERSION}"
388         exit
389 fi
390
391 command=$1
392 [ -z "$command" ] || shift
393
394 # ====================================================
395 # ================== FUNCTIONS =======================
396 # ====================================================
397
398 PORTSDIR=${PORTSDIR:-/usr/ports}
399
400 PORTS_MOVED_DB=${PORTSDIR}/MOVED
401 PORTS_INDEX_DB=${PORTSDIR}/INDEX-`uname -r | cut -d . -f 1`
402
403 WITH_PKGNG=`make -C "${PORTSDIR}" -V WITH_PKGNG | tr '[:upper:]' '[:lower:]'`
404
405 if [ "x$WITH_PKGNG" = xyes ]
406 then
407         which -s pkg || { echo "ERROR: WITH_PKGNG is set, but pkgng is not available" >&2; exit 1; }
408         command_pkg_info='pkg info'
409         command_pkg_create='pkg create'
410         command_pkg_delete='pkg delete'
411         command_pkg_add='pkg add'
412         pkg_info_qoa ()
413         {
414                 pkg info -qoa 2> /dev/null
415         }
416         pkg_info_qox ()
417         {
418                 pkg info -qox "$@" 2> /dev/null
419         }
420         pkg_info_qoX ()
421         {
422                 pkg info -qoX "$@" 2> /dev/null
423         }
424         pkg_info_qO ()
425         {
426                 pkg info -qO "$@" 2> /dev/null
427         }
428         pkg_info_qo ()
429         {
430                 pkg info -qo "$@" 2> /dev/null
431         }
432         pkg_info_qr ()
433         {
434                 pkg info -qd "$@" 2> /dev/null
435         }
436         pkg_info_e ()
437         {
438                 pkg info -e "$@" 2> /dev/null
439         }
440         pkg_info_qR ()
441         {
442                 pkg info -qr "$@" 2> /dev/null
443         }
444         pkg_info_Ex ()
445         {
446                 pkg info -Ex "$@" 2> /dev/null
447         }
448         pkg_info_origin_pattern_to_all_intsalled_origins ()
449         {
450                 local glob_pattern
451                 glob_pattern=$1
452                 pkg query -g '%o' "$glob_pattern"
453         }
454         pkg_create_b ()
455         {
456                 pkg create "$@"
457         }
458         pkg_delete_f ()
459         {
460                 pkg delete -fqy "$@"
461         }
462         pkg_add_f ()
463         {
464                 env ASSUME_ALWAYS_YES=YES pkg add "$@"
465         }
466         pkg_add_fF ()
467         {
468                 env ASSUME_ALWAYS_YES=YES pkg add "$@"
469         }
470 else
471         unset WITH_PKGNG
472         command_pkg_info='pkg_info'
473         command_pkg_create='pkg_create'
474         command_pkg_delete='pkg_delete'
475         command_pkg_add='pkg_add'
476         pkg_info_qoa ()
477         {
478                 pkg_info -qoa 2> /dev/null
479         }
480         pkg_info_qox ()
481         {
482                 pkg_info -qox "$@" 2> /dev/null
483         }
484         pkg_info_qoX ()
485         {
486                 pkg_info -qoX "$@" 2> /dev/null
487         }
488         pkg_info_qO ()
489         {
490                 pkg_info -qO "$@" 2> /dev/null
491         }
492         pkg_info_qo ()
493         {
494                 pkg_info -qo "$@" 2> /dev/null
495         }
496         pkg_info_qr ()
497         {
498                 pkg_info -qr "$@" | grep '^@pkgdep ' | sed 's/^@pkgdep[[:space:]]*//' 2> /dev/null
499         }
500         pkg_info_e ()
501         {
502                 pkg_info -e "$@" 2> /dev/null
503         }
504         pkg_info_qR ()
505         {
506                 pkg_info -qR "$@" | grep -v '^$' 2> /dev/null
507         }
508         pkg_info_Ex ()
509         {
510                 pkg_info -Ex "$@" 2> /dev/null
511         }
512         pkg_info_origin_pattern_to_all_intsalled_origins ()
513         {
514                 local glob_pattern
515                 glob_pattern=$1
516                 pkg_info -qO "$glob_pattern" | xargs pkg_info -qo
517         }
518         pkg_create_b ()
519         {
520                 pkg_create -b "$@"
521         }
522         pkg_delete_f ()
523         {
524                 pkg_delete -f "$@"
525         }
526         pkg_add_f ()
527         {
528                 pkg_add -f "$@"
529         }
530         pkg_add_fF ()
531         {
532                 pkg_add -fF "$@"
533         }
534 fi
535
536 str_escape_regexp_filter ()
537 {
538         sed 's/\\/\\\\/g;s/|/\\|/g;s/\./\\./g;s|/|\\/|g;s/\[/\\[/g;s/\]/\\]/g;s/[(]/\\(/g;s/[)]/\\)/g;s/\+/\\+/g;s/\?/\\?/g;s/\*/\\*/g'
539 }
540
541 convert_glob_to_regexp_pattern ()
542 {
543         sed 's/\+/\\+/g;s/\./\\./g;s|/|\\/|g;s/\*/.*/g;s/\?/g./;s/\[\!/[^/g;s/^/^/;s/$/$/'
544 }
545
546 convert_portsglob_to_regexp_pattern ()
547 {
548         local glob_pattern regexp_pattern
549         glob_pattern=$1
550         if expr "$glob_pattern" : '^:' > /dev/null 2>&1
551         then
552                 regexp_pattern=`echo "$glob_pattern" | sed 's/^://'`
553         else
554                 regexp_pattern=`echo "$glob_pattern" | convert_glob_to_regexp_pattern`
555         fi
556         echo "$regexp_pattern"
557 }
558
559 if which -s ports_glob
560 then
561         :
562 else
563         ports_glob ()
564         {
565                 local glob index
566                 [ -f "${DBDIR}/ports_glob:pkg.lst" ] || cut -d \| -f 1 "${PORTS_INDEX_DB}" > ${DBDIR}/ports_glob:pkg.lst
567                 [ -f "${DBDIR}/ports_glob:origin.lst" ] || cut -d \| -f 2 "${PORTS_INDEX_DB}" | sed -E "s/^`str_escape_regexp "${PORTSDIR}"`\///" > ${DBDIR}/ports_glob:origin.lst
568                 while [ $# -gt 0 ]
569                 do
570                         glob=`convert_portsglob_to_regexp_pattern "$1"`
571                         if expr "$glob" : '[^/][^/]*\/[^/][^/]*$' 2> /dev/null > /dev/null
572                         then
573                                 grep -E "$glob" "${DBDIR}/ports_glob:origin.lst" || :
574                                 pkg_info_qoa | grep -E "$glob" || :
575                         else
576                                 grep -n -E "$glob" "${DBDIR}/ports_glob:pkg.lst" | cut -d : -f 1 | while read index
577                                 do
578                                         sed -n ${index}p "${DBDIR}/ports_glob:origin.lst"
579                                 done || :
580                                 pkg_info_qox "$glob" || :
581                         fi
582                         shift
583                 done | sort -u
584         }
585 fi
586
587 str_escape_regexp ()
588 {
589         echo "$*" | str_escape_regexp_filter
590 }
591
592 create_backup_pkg ()
593 {
594         local pkgname dstdir backup_pkg
595         pkgname=$1
596         dstdir=$2
597         rm -rf "${TMPDIR}"/package.tmp
598         mkdir "${TMPDIR}"/package.tmp
599         if ( cd "${TMPDIR}"/package.tmp && pkg_create_b "$pkgname" )
600         then
601                 backup_pkg=`ls "${TMPDIR}"/package.tmp | \
602                         grep -m 1 -E "^`str_escape_regexp \"$pkgname\"`\.(txz|tbz|tgz|tar)$"` || :
603         fi
604         if [ -z "$backup_pkg" ]
605         then
606                 echo "WARNING: Failed to create backup package for $pkgname" >&2
607                 return 1
608         fi
609         [ -d "$dstdir" ] || mkdir -p "$dstdir"
610         mv "${TMPDIR}/package.tmp/$backup_pkg" "$dstdir"
611         echo "$dstdir/$backup_pkg"
612 }
613
614 rm_a_line ()
615 {
616         local item dstpath pattern
617         item=$1
618         dstpath=$2
619         pattern=`str_escape_regexp "$item"`
620         grep -v -E "^$pattern$" "$dstpath" 2> /dev/null > ${TMPDIR}/rm_a_line || :
621         mv "${TMPDIR}/rm_a_line" "$dstpath"
622 }
623
624 add_a_line_if_new ()
625 {
626         local item dstpath pattern
627         item=$1
628         dstpath=$2
629         pattern=`str_escape_regexp "$item"`
630         grep -m 1 -E "^$pattern$" "$dstpath" > /dev/null  2>&1 || echo "$item" >> $dstpath
631 }
632
633 record_success ()
634 {
635         local origin clean recurse
636         origin=$1
637         str_escape_regexp_filter < ${DBDIR}/failed.list | sed "s|^|^|; s|$|$|" > ${TMPDIR}/record_success.grep_failed.list.tmp
638         rm_a_line "$origin" "${DBDIR}/todo_after_requirements_succeed.list"
639         dbdir_esc=`echo "${DBDIR}/requires/" | sed 's/|/\\|/'`
640         if [ -e "${DBDIR}/requires/$origin/dependents" ]
641         then
642                 sed "s|^|$dbdir_esc|;s|$|/failed_requirements|" "${DBDIR}/requires/$origin/dependents" | \
643                         rm_a_line_from_files "$origin"
644         fi
645         if [ `grep -m 1 -E -f "${TMPDIR}/record_success.grep_failed.list.tmp" "${DBDIR}/requires/$origin/requires" | wc -l` -eq 0 ]
646         then
647                 add_a_line_if_new "$origin" "${DBDIR}/success.list"
648                 rm_a_line "$origin" "${DBDIR}/success_but_dependencies_failed.list"
649                 [ ! -e "${DBDIR}/requires/$origin/necessary_update" ] || mv "${DBDIR}/requires/$origin/necessary_update" "${DBDIR}/requires/$origin/necessary_update_completed"
650         else
651                 rm_a_line "$origin" "${DBDIR}/success.list"
652                 add_a_line_if_new "$origin" "${DBDIR}/success_but_dependencies_failed.list"
653         fi
654         rm_a_line "$origin" "${DBDIR}/failed.list"
655         touch "${DBDIR}/requires/$origin/succeeded_once"
656         rm -f "${DBDIR}/requires/$origin/note_failtre"
657 }
658
659 record_failure ()
660 {
661         local origin clean portsdir_esc
662         origin=$1
663         clean=$2
664         add_a_line_if_new "$origin" "${DBDIR}/failed.list"
665         rm_a_line "$origin" "${DBDIR}/success.list"
666         rm_a_line "$origin" "${DBDIR}/success_but_dependencies_failed.list"
667         rm_a_line "$origin" "${DBDIR}/todo_after_requirements_succeed.list"
668         dbdir_esc=`echo "${DBDIR}/requires/" | sed 's/|/\\|/'`
669         if [ -e "${DBDIR}/requires/$origin/dependents" ]
670         then
671                 sed "s|^|$dbdir_esc|;s|$|/failed_requirements|" "${DBDIR}/requires/$origin/dependents" | \
672                         add_a_line_to_files_if_new "$origin"
673         fi
674         rm -f "${DBDIR}/requires/$origin/succeeded_once"
675         if [ -z "$clean" -o "@$clean" = @clean ]
676         then
677                 echo "*** Trying to clean the failed build... (Ignore failures)"
678                 env ${MAKE_ENVS} make clean ${MAKE_ARGS} || :
679         fi
680         echo "*** Skipping this port and proceeding to the next one forcibly..."
681         echo
682 }
683
684 rm_a_line_from_files ()
685 {
686         local item
687         item=$1
688         while read filepath
689         do
690                 rm_a_line "$item" "$filepath"
691         done
692 }
693
694 add_a_line_to_files_if_new ()
695 {
696         local item
697         item=$1
698         while read filepath
699         do
700                 add_a_line_if_new "$item" "$filepath"
701         done
702 }
703
704 add_lines_if_new ()
705 {
706         local filepath origin advance
707         filepath=$1
708         advance=$2
709         while read origin
710         do
711                 grep -m 1 -E "^`str_escape_regexp $origin`$" "$filepath" 2> /dev/null > /dev/null || echo $origin
712         done > ${TMPDIR}/add_lines_if_new
713         if [ "@$advance" = @advance ]
714         then
715                 mv "$filepath" ${TMPDIR}/add_lines_if_new.bak
716                 cat "${TMPDIR}/add_lines_if_new" "${TMPDIR}/add_lines_if_new.bak" > $filepath
717         else
718                 cat "${TMPDIR}/add_lines_if_new" >> $filepath
719         fi
720 }
721
722 register_globs ()
723 {
724         local globlist listpath mode dirpath origin
725         globlist1=$1
726         globlist2=$2
727         listpath=$3
728         mode=$4
729         dirpath=`dirname "$listpath"`
730         echo "`echo "$globlist1" | sed 's/,/ /g'`" "$globlist2" | sed -E 's/ +/\
731 /g' | grep -v '^$' | while read glob
732         do
733                 if expr "@$glob" : '^@[^/][^/]*\/[^/][^/]*$' > /dev/null 2> /dev/null
734                 then
735                         [ ! -d "${PORTSDIR}/$glob" ] || { echo "$glob"; continue; }
736                 fi
737                 ports_glob "$glob" > ${TMPDIR}/register_globs:ports_glob
738                 origin=`ports_glob "$glob"`
739                 [ `cat "${TMPDIR}"/register_globs:ports_glob | wc -l` -ge 1 ] || \
740                 {
741                         echo "WARNING: No matching ports/package glob [$glob]" >&2
742                         continue
743                 }
744                 cat "${TMPDIR}"/register_globs:ports_glob
745         done | while read origin
746         do
747                 [ -d "$dirpath" ] || mkdir -p "$dirpath"
748                 if [ "@$mode" = @remove ]
749                 then
750                         rm_a_line "$origin" "$listpath"
751                 else
752                         add_a_line_if_new "$origin" "$listpath"
753                 fi
754         done
755 }
756
757 expand_glob_pattern_to_origins ()
758 {
759         local glob_pattern include_nonexistent regexp_pattern
760         glob_pattern=$1
761         include_nonexistent=$2
762         {
763                 ports_glob "$glob_pattern" 2> /dev/null || :
764                 if expr "$glob_pattern" : '^[a-z][a-z]*\/[a-zA-Z0-9_+-][a-zA-Z0-9_+-]*$' > /dev/null 2>&1
765                 then
766                         if [ "x$include_nonexistent" = xyes ]
767                         then
768                                 echo "$glob_pattern"
769                         else
770                                 pkg_info_origin_pattern_to_all_intsalled_origins "$glob_pattern"
771                         fi
772                 elif expr "$glob_pattern" : '^[a-zA-Z0-9.,_+-][a-zA-Z0-9.,_+-]*$' > /dev/null 2>&1
773                 then
774                         pkg_info_qo "$glob_pattern" 2> /dev/null || :
775                 else
776                         regexp_pattern=`convert_portsglob_to_regexp_pattern "$glob_pattern"`
777                         if expr "$glob_pattern" : '.*\/' > /dev/null 2>&1
778                         then
779                                 pkg_info_qoa | grep -E "$regexp_pattern" 2> /dev/null || :
780                         else
781                                 pkg_info_qoX "$regexp_pattern" 2> /dev/null || :
782                         fi
783                 fi
784         } | grep -v -e '^$' | sort -u
785 }
786
787 build_conflist_target_list ()
788 {
789         local section
790         section=$1
791         if [ ! -e "${DBDIR}/COMPLETE_REFLECTCONF_${section}" ]
792         then
793                 echo "-- ${section}_*"
794                 set | grep -e "^_CONF_${section}_" | cut -d = -f 1 | while read var
795                 do
796                         eval glob_pattern=\${$var}
797                         expand_glob_pattern_to_origins "$glob_pattern"
798                 done > ${DBDIR}/${section}_PORTS.conflist
799                 touch "${DBDIR}/COMPLETE_REFLECTCONF_${section}"
800         fi
801 }
802
803 build_conflist_target_val_pair ()
804 {
805         local section tag_target tag_val
806         section=$1
807         tag_target=$2
808         tag_val=$3
809         if [ ! -e "${DBDIR}/COMPLETE_REFLECTCONF_${section}" ]
810         then
811                 echo "-- ${section}_*"
812                 set | grep -e "^_CONF_${section}_${tag_target}_" | cut -d = -f 1 | while read var
813                 do
814                         eval glob_pattern=\${$var}
815                         eval val=\$\{`echo $var | sed "s/^_CONF_${section}_${tag_target}_/_CONF_${section}_${tag_val}_/"`\}
816                         expand_glob_pattern_to_origins "$glob_pattern" | while read origin
817                         do
818                                 path=${DBDIR}/requires_conflist/$origin
819                                 [ -d "$path" ] || mkdir -p "$path"
820                                 echo "$val" > $path/${section}.conflist
821                         done
822                 done
823                 touch "${DBDIR}/COMPLETE_REFLECTCONF_${section}"
824         fi
825 }
826
827 add_to_obsolete_if_not_yet ()
828 {
829         local origin pkgtag
830         origin=$1
831         add_a_line_if_new "$origin" "${DBDIR}/moved_or_lost.list"
832         if [ ! -e "${DBDIR}/obsolete/$origin/pkgtag" ]
833         then
834                 [ -d "${DBDIR}/obsolete/$origin" ] || mkdir -p "${DBDIR}/obsolete/$origin"
835                 pkgtag=`pkg_info_qO "$origin"`
836                 [ -n "$pkgtag" ] || pkgtag='[not installed]'
837                 echo "$pkgtag" > ${DBDIR}/obsolete/$origin/pkgtag
838         fi
839 }
840
841 convert_origin_if_moved ()
842 {
843         local origin_src recursedb_in recursedb iline_db date_moved why_moved
844         # input/output origin
845         origin_src=$1
846         recursedb_in=$2
847         recursedb=${recursedb_in:-${PORTS_MOVED_DB}}
848         [ ! -d "${PORTSDIR}/$origin" ] || return 0
849         add_to_obsolete_if_not_yet "$origin"
850         grep -n -m 1 -E "^`str_escape_regexp $origin`\|" "$recursedb" 2> /dev/null > ${TMPDIR}/moved.info || :
851         if [ `cat "${TMPDIR}/moved.info" | wc -l` -eq 0 ]
852         then
853                 if [ -n "$recursedb_in" ]
854                 then
855                         echo "${DEPTH_INDEX}  ===> Disappeared port (MOVED broken?)"
856                 else
857                         echo "${DEPTH_INDEX}  ===> Nonexistent port (your original?)"
858                 fi
859                 [ -z "$origin_src" ] || add_to_obsolete_if_not_yet "$origin_src"
860                 return 1
861         else
862                 iline_db=`cut -d : -f 1 "${TMPDIR}/moved.info"`
863                 sed 1,${iline_db}d "${PORTS_MOVED_DB}" > ${TMPDIR}/MOVED.DB
864                 origin=`sed -E 's/^[0-9]+://' "${TMPDIR}/moved.info" | cut -d '|' -f 2 || :`
865                 date_moved=`cut -d '|' -f 3 "${TMPDIR}/moved.info" || :`
866                 why_moved=`cut -d '|' -f 4 "${TMPDIR}/moved.info" || :`
867                 if [ -n "$origin" ]
868                 then
869                         echo "${DEPTH_INDEX}  ===> Moved to $origin at $date_moved because \"$why_moved\""
870                         convert_origin_if_moved "$origin_src" "${TMPDIR}/MOVED.DB" || return 1
871                 else
872                         echo "${DEPTH_INDEX}  ===> Deleted at $date_moved because \"$why_moved\""
873                         [ -n "$origin_src" ] || return 1
874                         origin=$origin_src
875                         echo "${DEPTH_INDEX}  ===> Going back to the original port $origin_src"
876                         convert_origin_if_moved || return 1
877                 fi
878         fi
879 }
880
881 inspect_dependencies ()
882 {
883         local origin origin_orig pkg origin_id origin_src port_exists origin_dependency DEPTH_INDEX_orig nlines iline is_suppressed
884         origin=$1
885         origin_orig=$origin
886         DEPTH_INDEX_orig=${DEPTH_INDEX}
887         DEPTH_INDEX="${DEPTH_INDEX}--"
888         echo "${DEPTH_INDEX} $origin"
889         origin_id=`echo $origin | tr / :`
890         pkg=`pkg_info_qO "$origin"`
891         if [ -n "$pkg" ]
892         then
893                 target_dir=${DBDIR}/initial/$origin
894                 [ -d "$target_dir" ] || mkdir -p "$target_dir"
895                 echo $pkg > $target_dir/installed_version
896                 pkg_info_qr "$pkg" | while read requirement
897                 do
898                         pkg_info_e "$requirement" || continue
899                         pkg_info_qo "$requirement" >> $target_dir/requires
900                 done
901                 pkg_info_qR "$pkg" | while read dependent
902                 do
903                         pkg_info_e "$dependent" || continue
904                         pkg_info_qo "$dependent" >> $target_dir/dependents
905                 done
906         fi
907         if [ $supress_self_upadte = yes -a `expr "$pkg" : "^${APPNAME}-[0-9].*"` -gt 0 ]
908         then
909                 is_supressed=yes
910         else
911                 is_supressed=no
912         fi
913         origin_src=
914         if [ `echo $origin | grep -m 1 -E -f "${DBDIR}/REPLACE.grep_from_pattern.conflist" | wc -l` -eq 1 ]
915         then
916                 origin_src=$origin
917                 origin=`echo $origin_src | sed -E -f "${DBDIR}/REPLACE.replace_pattern.conflist"`
918                 if [ "x$origin_src" != "x$origin" ]
919                 then
920                         if [ $is_supressed = yes ]
921                         then
922                                 if [ -n "$origin" ]
923                                 then
924                                         echo "${DEPTH_INDEX}  ===> Replaced with $origin by user configuration (ignored)"
925                                 else
926                                         echo "${DEPTH_INDEX}  ===> Deleted by user configuration (ignored)"
927                                 fi
928                         else
929                                 add_to_obsolete_if_not_yet "$origin_src"
930                                 if [ -n "$origin" ]
931                                 then
932                                         add_a_line_if_new "$origin" "${DBDIR}/replaced_target.inspected.list"
933                                         echo "${DEPTH_INDEX}  ===> Replaced with $origin by user configuration"
934                                 else
935                                         echo "${DEPTH_INDEX}  ===> Deleted by user configuration"
936                                 fi
937                         fi
938                 fi
939         fi
940         if [ -n "$origin" ]
941         then
942                 if convert_origin_if_moved "$origin_src" ''
943                 then
944                         port_exists=yes
945                 else
946                         port_exists=no
947                 fi
948                 if [ $port_exists = yes ]
949                 then
950                         rm_a_line "$origin" "${DBDIR}/moved_or_lost.list"
951                         cd "${PORTSDIR}/$origin"
952                         target_dir=${DBDIR}/requires/$origin
953                         [ -d "$target_dir/status" ] || mkdir -p "$target_dir/status"
954                         [ $is_supressed = no ] || touch "$target_dir/SUPPRESSED"
955                         if [ -d "${DBDIR}/requires_conflist/$origin" ]
956                         then
957                                 cp -R "${DBDIR}/requires_conflist/$origin/"* "$target_dir/" > /dev/null 2> /dev/null || :
958                         fi
959                         MAKE_ARGS="FORCE_PKG_REGISTER=yes DISABLE_VULNERABILITIES=yes `cat "$target_dir/MARG.conflist" 2> /dev/null || :`"
960                         MAKE_ENVS=`cat "$target_dir/MENV.conflist" 2> /dev/null || :`
961                         env ${MAKE_ENVS} make config-conditional ${MAKE_ARGS}
962                         pkg=`pkg_info_qO "$origin"`
963                         [ -z "$pkg" ] || echo $pkg > $target_dir/installed_version
964                         pkg_new=`(cd "${PORTSDIR}/$origin" && env ${MAKE_ENVS} make package-name ${MAKE_ARGS})`
965                         pkgtag=$pkg
966                         [ -n "$pkgtag" ] || pkgtag=$pkg_new
967                         if [ -z "$pkgtag" ]
968                         then
969                                 pkgtag='?'
970                         
971                         elif [ "z$pkg" != "z$pkg_new" ]
972                         then
973                                 echo $pkg_new > $target_dir/new_version
974                                 if [ -n "$pkg" ]
975                                 then
976                                         pkgtag="$pkg => $pkg_new"
977                                 else
978                                         pkgtag="[new] $pkg_new"
979                                 fi
980                         fi
981                         echo $pkgtag > $target_dir/pkgtag
982                         env ${MAKE_ENVS} make all-depends-list ${MAKE_ARGS} | sed -E "s/^`str_escape_regexp "${PORTSDIR}"`\///" > $target_dir/requires || :
983                         grep -E -f "${DBDIR}/REPLACE.grep_from_pattern.conflist" "$target_dir/requires" | grep -v -E "^`str_escape_regexp $origin`$" > ${TMPDIR}/replaced_target.tmp || :
984                         mv "$target_dir/requires" "$target_dir/requires.orig"
985                         sed -E -f "${DBDIR}/REPLACE.replace_pattern.conflist" "$target_dir/requires.orig" | grep -v '^$' > $target_dir/requires || :
986                         add_lines_if_new "${DBDIR}/replaced_target.list" < ${TMPDIR}/replaced_target.tmp
987                         grep -v -E -f "${DBDIR}/installed_ports.grep_pattern" "$target_dir/requires" > ${TMPDIR}/missing.$origin_id || :
988                         nlines=`cat "${TMPDIR}/missing.$origin_id" | wc -l`
989                         iline=1
990                         while [ $iline -le $nlines ]
991                         do
992                                 origin_dependency=`sed -n ${iline}p "${TMPDIR}/missing.$origin_id"`
993                                 iline=$(($iline+1))
994                                 if grep -m 1 -E "^`str_escape_regexp $origin_dependency`$" "${DBDIR}/target.inspected.list" > /dev/null 2> /dev/null
995                                 then
996                                         :
997                                 else
998                                         inspect_dependencies "$origin_dependency"
999                                 fi
1000                         done
1001                         rm "${TMPDIR}/missing.$origin_id"
1002                         env ${MAKE_ENVS} make fetch-urlall-list ${MAKE_ARGS} | sed -E 's|.*/([^/]+)$|\1|' | sort | uniq >> ${DBDIR}/distfiles.list
1003                 fi
1004         fi
1005         [ "$origin_orig" = "$origin" ] || echo "s|^`str_escape_regexp $origin_orig`$|$origin|" >> ${DBDIR}/REPLACE.complete_replace_pattern.tmp
1006         add_a_line_if_new "$origin" "${DBDIR}/target.inspected.list"
1007         rm_a_line "$origin" "${DBDIR}/target_ports.remain"
1008         if [ -n "$origin_src" ]
1009         then
1010                 add_a_line_if_new "$origin_src" "${DBDIR}/target.inspected.list"
1011                 rm_a_line "$origin_src" "${DBDIR}/target_ports.remain"
1012         fi
1013         echo "${DEPTH_INDEX}  ===> ok"
1014
1015         DEPTH_INDEX=${DEPTH_INDEX_orig}
1016 }
1017
1018 cmt_fail_reinst ()
1019 {
1020         local origin
1021         origin=$1
1022         echo "*** Giving up for this port $origin and proceeding to the next one forcibly..."
1023         echo
1024 }
1025
1026 timestamp ()
1027 {
1028         env LANG= date
1029 }
1030
1031 warn_update_ports ()
1032 {
1033         [ ${_STATUS_DB_OBSOLETE} = yes ] || return 0
1034         echo "WARNING: The Ports tree was updated after construction of the temporal database for ${APPNAME}." >&2
1035         echo "      You should consider executing " >&2
1036         echo "               ${APPNAME} clean" >&2
1037         echo "     to reset the temporal database unless you have special purposes." >&2
1038 }
1039
1040 linear_list ()
1041 {
1042         echo "$*" | sed -E 's/^ +//; s/ +$//; s/ +/, /; s/, ([^ ]+)$/ and \1/'
1043 }
1044
1045 chk_privilege ()
1046 {
1047         [ `id -u` -eq 0 ] || { echo "ERROR: Only the superuser can execute this command." >&2; exit 1; }
1048 }
1049
1050 combine_lists ()
1051 {
1052         local src_conf src_opt dst
1053         src_conf=$1
1054         src_opt=$2
1055         dst=$3
1056         cat "${DBDIR}/$src_conf" "${DBDIR}/$src_opt" 2> /dev/null | sort | uniq > ${DBDIR}/$dst || :
1057 }
1058
1059 show_list_failure ()
1060 {
1061         [ -e "${DBDIR}"/failed.list ] || return 0
1062         while read origin
1063         do
1064                 note=`cat "${DBDIR}/requires/$origin/note_failtre"`
1065                 if grep -m 1 -E "^`str_escape_regexp $origin`$" "${DBDIR}/manually_done.list" > /dev/null 2>&1
1066                 then
1067                         resolved=', resolved'
1068                 else
1069                         resolved=
1070                 fi
1071                 if [ -e "${DBDIR}/requires/$origin/pkgtag" ]
1072                 then
1073                         pkgtag=' ('`cat "${DBDIR}/requires/$origin/pkgtag"`')'
1074                 else
1075                         pkgtag=
1076                 fi
1077                 echo "$origin$pkgtag (error while [$note]$resolved)"
1078         done < ${DBDIR}/failed.list
1079 }
1080
1081 chk_if_target ()
1082 {
1083         local prefix _is_all _is_target _is_required _is_former_required _is_dependent _is_former_dependent _is_relevant
1084         prefix=$1
1085         origin=$2
1086         if [ -e "${DBDIR}/all/$origin/chk_if_target.param" ]
1087         then
1088                 . "${DBDIR}/all/$origin/chk_if_target.param"
1089         else
1090                 _is_all=y
1091                 _is_target=
1092                 _is_required=
1093                 _is_former_required=
1094                 _is_dependent=
1095                 _is_former_dependent=
1096                 _is_relevant=y
1097                 if [ `cat "${DBDIR}/target_required_ports.specified" 2> /dev/null | wc -l` -gt 0 ]
1098                 then
1099                         _is_all=
1100                         if grep -m 1 -E "^`str_escape_regexp $origin`$" "${DBDIR}/target_required_ports.specified" > /dev/null 2> /dev/null
1101                         then
1102                                 _is_target=y
1103                         elif [ -e "${DBDIR}/requires/$origin/dependents.pattern" ] && grep -m 1 -E -f "${DBDIR}/requires/$origin/dependents.pattern" "${DBDIR}/target_required_ports.specified" > /dev/null 2> /dev/null
1104                         then
1105                                 _is_required=y
1106                         elif [ -e "${DBDIR}/initial/$origin/dependents.pattern" ] && grep -m 1 -E -f "${DBDIR}/initial/$origin/dependents.pattern" "${DBDIR}/target_required_ports.specified" > /dev/null 2> /dev/null
1107                         then
1108                                 _is_former_required=y
1109                         fi
1110                 fi
1111                 if [ `cat "${DBDIR}/target_dependent_ports.specified" 2> /dev/null | wc -l` -gt 0 ]
1112                 then
1113                         _is_all=
1114                         if [ -n "${_is_target}" ] || grep -m 1 -E "^`str_escape_regexp $origin`$" "${DBDIR}/target_dependent_ports.specified" > /dev/null 2> /dev/null
1115                         then
1116                                 _is_target=y
1117                         elif [ -e "${DBDIR}/requires/$origin/requires.pattern" ] && grep -m 1 -E -f "${DBDIR}/requires/$origin/requires.pattern" "${DBDIR}/target_dependent_ports.specified" > /dev/null 2> /dev/null
1118                         then
1119                                 _is_dependent=y
1120                         elif [ -e "${DBDIR}/initial/$origin/requires.pattern" ] && grep -m 1 -E -f "${DBDIR}/initial/$origin/requires.pattern" "${DBDIR}/target_dependent_ports.specified" > /dev/null 2> /dev/null
1121                         then
1122                                 _is_former_dependent=y
1123                         fi
1124                 fi
1125                 [ -n "${_is_all}${_is_target}${_is_required}${_is_former_required}${_is_dependent}${_is_former_dependent}" ] || _is_relevant=
1126                 echo _is_all=${_is_all} > ${TMPDIR}/chk_if_target:results
1127                 echo _is_target=${_is_target} >> ${TMPDIR}/chk_if_target:results
1128                 echo _is_required=${_is_required} >> ${TMPDIR}/chk_if_target:results
1129                 echo _is_former_required=${_is_former_required} >> ${TMPDIR}/chk_if_target:results
1130                 echo _is_dependent=${_is_dependent} >> ${TMPDIR}/chk_if_target:results
1131                 echo _is_former_dependent=${_is_former_dependent} >> ${TMPDIR}/chk_if_target:results
1132                 echo _is_relevant=${_is_relevant} >> ${TMPDIR}/chk_if_target:results
1133                 [ -d "${DBDIR}/all/$origin" ] || mkdir -p "${DBDIR}/all/$origin"
1134                 mv "${TMPDIR}"/chk_if_target:results "${DBDIR}/all/$origin/chk_if_target.param"
1135         fi
1136         eval ${prefix}_is_all=\$\{_is_all\}
1137         eval ${prefix}_is_target=\$\{_is_target\}
1138         eval ${prefix}_is_required=\$\{_is_required\}
1139         eval ${prefix}_is_former_required=\$\{_is_former_required\}
1140         eval ${prefix}_is_dependent=\$\{_is_dependent\}
1141         eval ${prefix}_is_former_dependent=\$\{_is_former_dependent\}
1142         eval ${prefix}_is_relevant=\$\{_is_relevant\}
1143 }
1144
1145 register_globs_only_installed ()
1146 {
1147         local src1 src2
1148         src1=$1
1149         src2=$2
1150         rm -f "${TMPDIR}/register_globs_only_installed:origins"
1151         register_globs "$src1" "$src2" "${TMPDIR}/register_globs_only_installed:origins"
1152         [ -e "${TMPDIR}/register_globs_only_installed:origins" ] || return 0
1153         while read origin
1154         do
1155                 [ -z `pkg_info_qO "$origin"` ] || echo $origin
1156         done < ${TMPDIR}/register_globs_only_installed:origins
1157 }
1158
1159
1160 # ==================================================
1161 # ==================== MAIN ========================
1162 # ==================================================
1163
1164 # Title
1165 credit
1166 echo
1167 echo " Don't hesitate to terminate by CTRL+C anytime you feel the system is heavy to"
1168 echo "use because you can restart the operation from the terminated point quickly."
1169 echo
1170 echo "The current time is `timestamp`"
1171 echo
1172
1173 # Check of conflicting option
1174 [ -z "$target_dependent_ports" -o ! -e "${DBDIR}/COMPLETE_PARSE_OPTION_TARGET_PORTS" ] || echo "WARNING: -t option is specified but ignored because we are restarting the previous run." >&2
1175 [ -z "$target_required_ports" -o ! -e "${DBDIR}/COMPLETE_PARSE_OPTION_TARGET_PORTS" ] || echo "WARNING: -T option is specified but ignored because we are restarting the previous run." >&2
1176 [ -z "$target_dependent_ports_form2" -o ! -e "${DBDIR}/COMPLETE_PARSE_OPTION_TARGET_PORTS" ] || echo "WARNING: -r option is specified but ignored because we are restarting the previous run." >&2
1177 [ -z "$target_required_ports_form2" -o ! -e "${DBDIR}/COMPLETE_PARSE_OPTION_TARGET_PORTS" ] || echo "WARNING: -R option is specified but ignored because we are restarting the previous run." >&2
1178 [ "$load_pkgtoolsconf" = undef -o ! -e "${DBDIR}/COMPLETE_IMPORT_PKGTOOLS_CONF" ] || echo "WARNING: -p, -P or -Q option is specified but ignored by following the previous settings." >&2
1179
1180 # Check whether the temporal database is newer than the ports tree
1181 if [ "${PORTS_INDEX_DB}" -nt "${DBDIR}"/MYVERSION ]
1182 then
1183         if [ $supress_obsolete_db_clean = no ]
1184         then
1185                 _STATUS_DB_OBSOLETE=no
1186                 if [ "z${command}" != zclean ]
1187                 then
1188                         echo "INFO: The temporal database is cleaned up because it is older than the ports tree."
1189                         echo
1190                         rm -rf "${DBDIR}"
1191                 fi
1192         else
1193                 _STATUS_DB_OBSOLETE=yes
1194         fi
1195 else
1196         _STATUS_DB_OBSOLETE=no
1197 fi
1198
1199 # Update ports-mgmt/pkg if it is newer in the ports tree
1200 if [ "x$WITH_PKGNG" = xyes -a $supress_pkgng_upadte = no -a `id -u` -eq 0 -a \( ! -e "${DBDIR}" -o ${_STATUS_DB_OBSOLETE} = yes \) ]
1201 then
1202         pkg_info_qO ports-mgmt/pkg > ${TMPDIR}/pkgng_version || :
1203         num_pkgng_versions=`cat "${TMPDIR}"/pkgng_version | wc -l`
1204         if [ $num_pkgng_versions -gt 1 ]
1205         then
1206                 echo "ERROR: Multiple versions of ports-mgmt/pkg are installed. This is unexpected." >&2
1207                 exit 1
1208         elif [ $num_pkgng_versions -eq 1 ]
1209         then
1210                 [ -d "${PORTSDIR}/ports-mgmt/pkg" ] || { echo "ERROR: ${PORTSDIR}/ports-mgmt/pkg does not exist" >&2; exit 1; }
1211                 pkgng_pkg_current=`cat "${TMPDIR}"/pkgng_version`
1212                 pkgng_pkg_new=`make -C "${PORTSDIR}/ports-mgmt/pkg" package-name`
1213                 if [ -n "$pkgng_pkg_new" ]
1214                 then
1215                         if [ "$pkgng_pkg_new" != `cat "${TMPDIR}"/pkgng_version` ]
1216                         then
1217                                 echo "INFO: The ports tree has a new version of ports-mgmt/pkg. It will be updated first."
1218                                 echo "Updating ports-mgmt/pkg ($pkgng_pkg_current => $pkgng_pkg_new)..."
1219                                 echo "Backing up the installed package..."
1220                                 backup_pkg=`create_backup_pkg "$pkgng_pkg_current" "${PORTSDIR}"/packages/All` || :
1221                                 echo "Reinstalling ports-mgmt/pkg..."
1222                                 pkg_delete_f "$pkgng_pkg_current"
1223                                 if make -C "${PORTSDIR}/ports-mgmt/pkg" reinstall
1224                                 then
1225                                         make -C "${PORTSDIR}/ports-mgmt/pkg" clean
1226                                 else
1227                                         echo "WARNING: Reinstallation failed. Restoring the old package..." >&2
1228                                         make -C "${PORTSDIR}/ports-mgmt/pkg" deinstall || :
1229                                         make -C "${PORTSDIR}/ports-mgmt/pkg" clean || :
1230                                         [ -n "$backup_pkg" ] && pkg_add_f "$backup_pkg"
1231                                         echo "INFO: Continuing with the old version..."
1232                                 fi
1233                         fi
1234                 else
1235                         echo "WARNING: No port for ports-mgmt/pkg exists in the current ports tree" >&2
1236                 fi
1237         fi
1238 fi
1239
1240 # Update portsreinstall itself if it is newer in the ports tree
1241 if [ $supress_self_upadte = no -a `id -u` -eq 0 -a \( ! -e "${DBDIR}" -o ${_STATUS_DB_OBSOLETE} = yes \) ]
1242 then
1243         pkg_info_Ex "${APPNAME}-[0-9].*" > ${TMPDIR}/self_version || :
1244         num_self_versions=`cat "${TMPDIR}"/self_version | wc -l`
1245         if [ $num_self_versions -gt 1 ]
1246         then
1247                 echo "ERROR: Multiple versions of ${APPNAME} are installed. This is unexpected." >&2
1248                 exit 1
1249         elif [ $num_self_versions -eq 1 ]
1250         then
1251                 self_origin=`pkg_info_qo "\`cat \"${TMPDIR}\"/self_version\`"`
1252                 [ -d "${PORTSDIR}/$self_origin" ] || { echo "ERROR: ${PORTSDIR}/$self_origin does not exist" >&2; exit 1; }
1253                 self_pkg_current=`cat "${TMPDIR}"/self_version`
1254                 self_pkg_new=`make -C "${PORTSDIR}/$self_origin" package-name`
1255                 if [ -n "$self_pkg_new" ]
1256                 then
1257                         if [ "$self_pkg_new" != `cat "${TMPDIR}"/self_version` ]
1258                         then
1259                                 echo "INFO: The ports tree has a new version of ${APPNAME}. It will be updated first."
1260                                 echo "Updating $self_origin ($self_pkg_current => $self_pkg_new)..."
1261                                 echo "Backing up the installed package..."
1262                                 backup_pkg=`create_backup_pkg "$self_pkg_current" "${PORTSDIR}"/packages/All` || :
1263                                 echo "Reinstalling ${APPNAME}..."
1264                                 pkg_delete_f "$self_pkg_current"
1265                                 if make -C "${PORTSDIR}/$self_origin" reinstall
1266                                 then
1267                                         make -C "${PORTSDIR}/$self_origin" clean
1268                                         if [ $supress_obsolete_db_clean = yes -a -d "${DBDIR}" ]
1269                                         then
1270                                                 echo "INFO: Cleaning the temporal database..."
1271                                                 rm -rf "${DBDIR}"
1272                                                 echo
1273                                         fi
1274                                         echo "INFO: Restarting with the new version..."
1275                                         echo
1276                                         . "${TMPDIR}"/restart_command.sh
1277                                         echo "ERROR: Failed to launch the new version" >&2
1278                                         exit 1
1279                                 else
1280                                         echo "WARNING: Reinstallation failed. Restoring the old package..." >&2
1281                                         make -C "${PORTSDIR}/$self_origin" deinstall || :
1282                                         make -C "${PORTSDIR}/$self_origin" clean || :
1283                                         [ -n "$backup_pkg" ] && pkg_add_f "$backup_pkg"
1284                                         echo "INFO: Continuing with the old version..."
1285                                 fi
1286                         fi
1287                 else
1288                         echo "WARNING: No port for ${APPNAME} exists in the current ports tree" >&2
1289                 fi
1290         else
1291                 echo "INFO: This version of ${APPNAME} has been installed not by ports/packages mechanism."
1292                 echo "Thus any updates on ${APPNAME} will be ignored."
1293         fi
1294 fi
1295
1296 # Creation of temporal database directory
1297 if [ -d "${DBDIR}" ]
1298 then
1299         DBVERSION=`cat "${DBDIR}"/MYVERSION 2> /dev/null || :`
1300         # Reserved for compatibility check
1301 else
1302         mkdir -p "${DBDIR}"
1303         echo ${MYVERSION} > ${DBDIR}/MYVERSION
1304 fi
1305
1306 # Taboo list given by options
1307 register_globs "$taboo_ports" "$taboo_ports_form2" "${DBDIR}/taboo.list"
1308
1309 # ------- Commands -------
1310
1311 # Special modes
1312 case ${command:-do} in
1313 clean)
1314         chk_privilege
1315         echo "Starting to clean up the temporal database..."
1316         rm -rf "${DBDIR}"
1317         echo "Done"
1318         exit
1319         ;;
1320 ok)
1321         chk_privilege
1322         warn_update_ports
1323         opr=$1
1324         shift
1325         [ -e "${DBDIR}/manually_done.list" ] || touch "${DBDIR}/manually_done.list"
1326         cp "${DBDIR}/manually_done.list" "${TMPDIR}/manually_done.list.old"
1327         case $opr in
1328         add)
1329                 register_globs '' "$*" "${DBDIR}/manually_done.list"
1330                 echo "`linear_list \"$*\"` is/are registered to the list of manually resolved ports"
1331                 ;;
1332         del)
1333                 register_globs '' "$*" "${DBDIR}/manually_done.list" remove
1334                 echo "`linear_list \"$*\"` is/are deregistered from the list of manually resolved ports"
1335                 ;;
1336         esac
1337         if diff "${TMPDIR}/manually_done.list.old" "${DBDIR}/manually_done.list" > ${TMPDIR}/manually_done.list.diff
1338         then
1339                 :
1340         else
1341                 grep '^<' "${TMPDIR}/manually_done.list.diff" 2> /dev/null | sed 's/^< //' | while read origin
1342                 do
1343                         record_failure "$origin"
1344                 done
1345                 grep '^>' "${TMPDIR}/manually_done.list.diff" 2> /dev/null | sed 's/^> //' | while read origin
1346                 do
1347                         record_success "$origin"
1348                 done
1349         fi
1350         echo "Now the following ports have been manually resolved:"
1351         [ ! -r "${DBDIR}/manually_done.list" ] || cat  "${DBDIR}/manually_done.list"
1352         exit
1353         ;;
1354 taboo)
1355         chk_privilege
1356         warn_update_ports
1357         opr=$1
1358         shift
1359         case $opr in
1360         add)
1361                 register_globs '' "$*" "${DBDIR}/taboo.list"
1362                 echo "`linear_list \"$*\"` is/are registered to the list of ports to be ignored."
1363                 ;;
1364         del)
1365                 register_globs '' "$*" "${DBDIR}/taboo.list" remove
1366                 echo "`linear_list \"$*\"` is/are deregistered from the list of ports to be ignored."
1367                 ;;
1368         esac
1369         combine_lists TABOO_PORTS.conflist taboo.list taboo.all.list
1370         echo "Now the following ports are registered to be ignored:"
1371         cat "${DBDIR}/taboo.all.list"
1372         exit
1373         ;;
1374 save)
1375         chk_privilege
1376         [ -d "${DBDIR}" ] || { echo "ERROR: Database has not been built up yet." >&2; exit 1; }
1377         savedir=$1
1378         [ -n "$savedir" ] || { echo "ERROR: Directory to save the temporal database archive is not specified." >&2; exit 1; }
1379         [ -d "$savedir" ] || { echo "ERROR: Directory [$savedir] is not found." >&2; exit 1; }
1380         srcdir=`dirname "${DBDIR}"`
1381         srcnode=`basename "${DBDIR}"`
1382         savefile=`realpath "$savedir"`/${APPNAME}_`date +%Y%m%d_%H%M%S`.tar.gz
1383         echo "Starting to save the temporal database as [$savefile]..."
1384         ( cd "$srcdir" && tar czf "$savefile" "$srcnode" )
1385         echo "Done"
1386         exit
1387         ;;
1388 load)
1389         chk_privilege
1390         loadfile=$1
1391         [ -n "$loadfile" ] || { echo "ERROR: Database archive is not specified." >&2; exit 1; }
1392         [ -f "$loadfile" ] || { echo "ERROR: Database archive is not found." >&2; exit 1; }
1393         loadfile=`realpath "$loadfile"`
1394         echo "Starting to load the temporal database..."
1395         rm -rf "${DBDIR}"
1396         srcdir=`dirname "${DBDIR}"`
1397         srcnode=`basename "${DBDIR}"`
1398         [ -d "$srcdir" ] || mkdir -p "$srcdir"
1399         ( cd "$srcdir" && tar xzf "$loadfile" )
1400         echo "Done"
1401         exit
1402         ;;
1403 show)
1404         [ -e "${DBDIR}/COMPLETE_PREPARATION" ] || { echo "ERROR: Database has not built yet." >&2; exit 1; }
1405         warn_update_ports
1406         _filter_skip_unchanged=
1407         _filter_only_target=
1408         _for_each_matching_port=
1409         pkgnamedb=requires
1410         case ${1:-todo} in
1411         todo)
1412                 echo "The following ports are to be reinstalled or newly installed in the current do/redo"
1413                 echo "process:"
1414                 list=reinst_todo.list
1415                 [ -e "${DBDIR}/reinst_todo.list" ] || list=reinst_order.list
1416                 _filter_skip_unchanged=necessary_update
1417                 _filter_only_target=y
1418                 ;;
1419         done)
1420                 echo "The following ports have been successfully reinstalled or newly installed:"
1421                 list=success.list
1422                 _filter_skip_unchanged=necessary_update_completed
1423                 _filter_only_target=y
1424                 ;;
1425         redo)
1426                 echo "The following ports themselves have been successfully reinstalled or newly installed,"
1427                 echo "but are to be reinstalled again because their dependencies were failed:"
1428                 list=success_but_dependencies_failed.list
1429                 _filter_skip_unchanged=necessary_update
1430                 _filter_only_target=y
1431                 ;;
1432         pending)
1433                 echo "The following ports need reinstalltion but are to be skipped until their requirements"
1434                 echo "succeed:"
1435                 list=todo_after_requirements_succeed.list
1436                 _filter_skip_unchanged=necessary_update
1437                 _filter_only_target=y
1438                 ;;
1439         resolved)
1440                 echo "The following ports had problems which have been manually resolved:"
1441                 list=manually_done.list
1442                 ;;
1443         failure)
1444                 echo "The following ports experienced failures and kept to be old:"
1445                 show_list_failure
1446                 exit
1447                 ;;
1448         taboo)
1449                 echo "The following ports are registered as taboo:"
1450                 list=taboo.all.list
1451                 ;;
1452         deleted)
1453                 echo "The following ports are to be or have been deleted:"
1454                 list=moved_or_lost.actual.list
1455                 pkgnamedb=obsolete
1456                 _filter_only_target=y
1457                 ;;
1458         requirements)
1459                 grandtitle="Dependencies based on the latest ports tree"
1460                 title="The following ports are required by %s:"
1461                 list=requires
1462                 _for_each_matching_port=y
1463                 ;;
1464         dependents)
1465                 grandtitle="Dependencies based on the latest ports tree"
1466                 title="The following ports depend on %s:"
1467                 list=dependents
1468                 _for_each_matching_port=y
1469                 ;;
1470         *)
1471                 echo "ERROR: Invalid show argument [$1]" >&2
1472                 exit 1
1473                 ;;
1474         esac
1475         [ -n "${_for_each_matching_port}" -o -r "${DBDIR}/$list" ] || exit 0
1476         [ ! -e "${DBDIR}"/saved_options.sh ] || . "${DBDIR}"/saved_options.sh
1477         if [ -n "${_for_each_matching_port}" ]
1478         then
1479                 shift
1480                 [ $# -gt 0 ] || { echo "ERROR: the argument as port glob is missing" >&2; exit 1; }
1481                 echo "[$grandtitle]"
1482                 echo
1483                 isfirst=y
1484                 for origin_target in `ports_glob "$@"`
1485                 do
1486                         [ -e "${DBDIR}/requires/$origin_target/pkgtag" ] || continue
1487                         [ "$isfirst" = y ] || echo
1488                         isfirst=n
1489                         pkg_target=`cat "${DBDIR}/$pkgnamedb/$origin_target/pkgtag"`
1490                         printf "$title\n" "$origin_target ($pkg_target)"
1491                         [ -e "${DBDIR}/requires/$origin_target/$list" ] || continue
1492                         while read origin
1493                         do
1494                                 if [ -e "${DBDIR}/$pkgnamedb/$origin/pkgtag" ]
1495                                 then
1496                                         echo $origin '('`cat "${DBDIR}/$pkgnamedb/$origin/pkgtag"`')'
1497                                 else
1498                                         echo $origin
1499                                 fi
1500                         done < ${DBDIR}/requires/$origin_target/$list
1501                 done
1502                 [ "$isfirst" = n ] || { echo "ERROR: no matching port for the glob" >&2; exit 1; }
1503         elif [ -n "${_filter_skip_unchanged}" -a $skip_unchanged = yes ]
1504         then
1505                 while read origin
1506                 do
1507                         [ -e "${DBDIR}/requires/$origin/${_filter_skip_unchanged}" ] || continue
1508                         if [ -n "${_filter_only_target}" ]
1509                         then
1510                                 chk_if_target currentorigin "$origin"
1511                                 [ -n "${currentorigin_is_relevant}" ] || continue
1512                                 [ ! -e "${DBDIR}/requires/$origin/SUPPRESSED" ] || continue
1513                         fi
1514                         if [ -e "${DBDIR}/$pkgnamedb/$origin/pkgtag" ]
1515                         then
1516                                 echo $origin '('`cat "${DBDIR}/$pkgnamedb/$origin/pkgtag"`')'
1517                         else
1518                                 echo $origin
1519                         fi
1520                 done < ${DBDIR}/$list
1521         else
1522                 while read origin
1523                 do
1524                         if [ -n "${_filter_only_target}" ]
1525                         then
1526                                 chk_if_target currentorigin "$origin"
1527                                 [ -n "${currentorigin_is_relevant}" ] || continue
1528                                 [ ! -e "${DBDIR}/requires/$origin/SUPPRESSED" ] || continue
1529                         fi
1530                         if [ -e "${DBDIR}/$pkgnamedb/$origin/pkgtag" ]
1531                         then
1532                                 echo $origin '('`cat "${DBDIR}/$pkgnamedb/$origin/pkgtag"`')'
1533                         else
1534                                 echo $origin
1535                         fi
1536                 done < ${DBDIR}/$list
1537         fi
1538         exit
1539         ;;
1540 redo)
1541         chk_privilege
1542         warn_update_ports
1543         touch "${DBDIR}/MODE_REDO"
1544         rm -f "${DBDIR}/COMPLETE_CLEANUP_REINST_STATUS"
1545         [ $renew_options = no ] || rm -f "${DBDIR}/COMPLETE_SAVE_OPTIONS"
1546         if [ -n "$target_required_ports$target_dependent_ports$target_required_ports_form2$target_dependent_ports_form2" ]
1547         then
1548                 rm -f "${DBDIR}/COMPLETE_PARSE_OPTION_TARGET_PORTS"
1549                 touch "${DBDIR}/REQUIRE_CHK_NEW_TARGET"
1550         fi
1551         echo "[REDO mode]"
1552         ;;
1553 prepare)
1554         chk_privilege
1555         warn_update_ports
1556         ;;
1557 do)
1558         chk_privilege
1559         ;;
1560 *)
1561         echo "ERROR: Invalid command [$command]" >&2
1562         exit 1
1563         ;;
1564 esac
1565
1566 # ------- Termination messages during construction of the temporal database -------
1567
1568 terminate_process_common ()
1569 {
1570         local msg_where
1571         [ -z "${_MSG_CURRENT_STAGE}" ] || msg_where=" during ${_MSG_CURRENT_STAGE}"
1572         echo
1573         if [ $errno -eq 130 ]
1574         then
1575                 echo "INFO: Terminated at `timestamp`$msg_where"
1576                 echo
1577                 echo " You can restart this process from the terminated point by"
1578         else
1579                 echo "INFO: Aborted at `timestamp`$msg_where"
1580                 echo
1581                 echo " You may restart this process from the aborted point by"
1582         fi
1583         echo "executing without options or arguments as:"
1584         echo "  ${APPNAME}"
1585 }
1586
1587 terminate_process ()
1588 {
1589         terminate_process_common
1590         fold -s << eof
1591  Instead, if you only want to construct the temporal database so as to stop before the actual reinstallation, execute as:
1592   ${APPNAME} prepare
1593 eof
1594         terminate_process ()
1595         {
1596         }
1597 }
1598
1599 # ------- Load from pkgtools.conf(5) -------
1600
1601 if [ ! -e "${DBDIR}/COMPLETE_SAVE_OPTIONS" ]
1602 then
1603         [ ! -e "${DBDIR}"/saved_options.sh ] || echo "(Previous option settings for '-s', '-q' and '-d' are reset.)"
1604         set | grep -e '^target_dependent_ports=' \
1605                 -e '^target_required_ports=' \
1606                 -e '^target_dependent_ports_form2=' \
1607                 -e '^target_required_ports_form2=' \
1608                 -e '^taboo_ports=' \
1609                 -e '^taboo_ports_form2=' \
1610                 -e '^load_pkgtoolsconf=' \
1611                 -e '^avoid_vulner=' \
1612                 -e '^skip_unchanged=' \
1613                 -e '^keep_distfiles=' \
1614                 -e '^renew_options=' \
1615                 -e '^supress_self_upadte=' \
1616                 -e '^supress_obsolete_db_clean=' \
1617                 > ${DBDIR}/saved_options.sh || :
1618         touch "${DBDIR}/COMPLETE_SAVE_OPTIONS"
1619 else
1620         t_avoid_vulner=$avoid_vulner
1621         t_skip_unchanged=$skip_unchanged
1622         t_keep_distfiles=$keep_distfiles
1623         . "${DBDIR}"/saved_options.sh
1624         [ $t_avoid_vulner = no -o $t_avoid_vulner = $avoid_vulner ] || echo "WARNING: -s option is specified but ignored by transferring the settings from the previous run." >&2
1625         [ $t_skip_unchanged = no -o $t_skip_unchanged = $skip_unchanged ] || echo "WARNING: -q option is specified but ignored by transferring the settings from the previous run." >&2
1626         [ $t_keep_distfiles = no -o $t_keep_distfiles = $keep_distfiles ] || echo "WARNING: -d option is specified but ignored by transferring the settings from the previous run." >&2
1627 fi
1628
1629 echo "INFO: List of option values:"
1630 echo "-----------------------------------------"
1631 cat "${DBDIR}"/saved_options.sh
1632 echo "-----------------------------------------"
1633 echo
1634
1635 if [ ! -e "${DBDIR}/COMPLETE_IMPORT_PKGTOOLS_CONF" ]
1636 then
1637         PORTUPGRADE=`which portupgrade | head -n 1 || :`
1638         if [ $load_pkgtoolsconf = undef ]
1639         then
1640                 if [ -n "${PORTUPGRADE}" -a -e /usr/local/etc/pkgtools.conf ]
1641                 then
1642                         load_pkgtoolsconf=default
1643                 else
1644                         load_pkgtoolsconf=no
1645                 fi
1646         elif [ $load_pkgtoolsconf != undef -a `which portupgrade | wc -l` -eq 0 ]
1647         then
1648                 echo "WARNING: pkgtools.conf is ignored because portupgrade is not installed" >&2
1649                 load_pkgtoolsconf=no
1650         fi
1651         
1652         if [ $load_pkgtoolsconf != no ]
1653         then
1654                 echo "-- Starting to parse pkgtools.conf at `timestamp` (by using installed portupgrade)"
1655                 portupgrade_pkg=`pkg_info_qO ports-mgmt/portupgrade`
1656                 [ -n "$portupgrade_pkg" ] || portupgrade_pkg=`pkg_info_qO ports-mgmt/portupgrade-devel`
1657                 [ `expr "$portupgrade_pkg" : '^portupgrade-devel-'` -eq 0 ] || echo "WARNING: Combination with portupgrade-devel-* has not tested."
1658                 istart=`grep -m 1 -n -e '^def init_global$' "${PORTUPGRADE}" | cut -d : -f 1` || :
1659                 [ -n "$istart" ] || { echo "ERROR: The current installed version of portupgrade is unsupported." >&2; }
1660                 sed 1,$(($istart-1))d "${PORTUPGRADE}" > ${TMPDIR}/portupgrade.0
1661                 iend=`grep -m 1 -n -e '^end$' "${TMPDIR}"/portupgrade.0 | cut -d : -f 1`
1662                 sed -n 1,${iend}p "${TMPDIR}"/portupgrade.0 > ${TMPDIR}/portupgrade.init_global
1663                 ruby > ${DBDIR}/pkgtools.conf.converted << eof
1664 MYNAME = 'portupgrade'
1665 require 'pkgtools'
1666 `cat "${TMPDIR}"/portupgrade.init_global`
1667 init_global
1668 init_pkgtools_global
1669 load_config
1670 alt_moved = config_value(:ALT_MOVED)
1671 hold_pkgs = config_value(:HOLD_PKGS)
1672 ignore_moved = config_value(:IGNORE_MOVED)
1673 alt_pkgdep = config_value(:ALT_PKGDEP)
1674 make_args = config_value(:MAKE_ARGS)
1675 make_env = config_value(:MAKE_ENV)
1676 beforebuild = config_value(:BEFOREBUILD)
1677 beforedeinstall = config_value(:BEFOREDEINSTALL)
1678 afterinstall = config_value(:AFTERINSTALL)
1679
1680 printf("ENV_PORTSDIR=%s\n", ENV['PORTSDIR'])
1681
1682 i = 0
1683 alt_moved.each do |val|
1684         printf("ALT_MOVED_pkgtoolsconf_%d_='%s'\n", i, val)
1685         i = i + 1
1686 end
1687
1688 i = 0
1689 hold_pkgs.each do |val|
1690         printf("HOLD_pkgtoolsconf_%d_='%s'\n", i, val)
1691         i = i + 1
1692 end
1693 ignore_moved.each do |val|
1694         printf("HOLD_pkgtoolsconf_%d_='%s'\n", i, val)
1695         i = i + 1
1696 end
1697
1698 i = 0
1699 alt_pkgdep.each do |pat, alt|
1700         printf("REPLACE_FROM_pkgtoolsconf_%d_='%s'\n", i, pat)
1701         printf("REPLACE_TO_pkgtoolsconf_%d_='%s'\n", i, alt)
1702         i = i + 1
1703 end
1704
1705 i = 0
1706 make_args.each do |target, definition|
1707         printf("MARG_TARGET_pkgtoolsconf_%d_='%s'\n", i, target)
1708         printf("MARG_DEF_pkgtoolsconf_%d_='%s'\n", i, definition)
1709         i = i + 1
1710 end
1711
1712 i = 0
1713 make_env.each do |target, definition|
1714         printf("MENV_TARGET_pkgtoolsconf_%d_='%s'\n", i, target)
1715         printf("MENV_DEF_pkgtoolsconf_%d_='%s'\n", i, definition)
1716         i = i + 1
1717 end
1718
1719 i = 0
1720 beforebuild.each do |target, command|
1721         printf("BEFOREBUILD_TARGET_pkgtoolsconf_%d_='%s'\n", i, target)
1722         printf("BEFOREBUILD_COMMAND_pkgtoolsconf_%d_='%s'\n", i, command)
1723         i = i + 1
1724 end
1725
1726 i = 0
1727 beforedeinstall.each do |target, command|
1728         printf("BEFOREDEINSTALL_TARGET_pkgtoolsconf_%d_='%s'\n", i, target)
1729         printf("BEFOREDEINSTALL_COMMAND_pkgtoolsconf_%d_='%s'\n", i, command)
1730         i = i + 1
1731 end
1732
1733 i = 0
1734 afterinstall.each do |target, command|
1735         printf("AFTERINSTALL_TARGET_pkgtoolsconf_%d_='%s'\n", i, target)
1736         printf("AFTERINSTALL_COMMAND_pkgtoolsconf_%d_='%s'\n", i, command)
1737         i = i + 1
1738 end
1739 eof
1740                 if [ $load_pkgtoolsconf = default ]
1741                 then
1742                         cat "${DBDIR}"/pkgtools.conf.converted "${CONFFILE}" > ${DBDIR}/setup.conf 
1743                 elif [ $load_pkgtoolsconf = override ]
1744                 then
1745                         cat "${CONFFILE}" "${DBDIR}"/pkgtools.conf.converted > ${DBDIR}/setup.conf
1746                 fi
1747                 echo "===> ok"
1748                 echo
1749         else
1750                 ln -s "${CONFFILE}" "${DBDIR}"/setup.conf
1751         fi
1752         touch "${DBDIR}/COMPLETE_IMPORT_PKGTOOLS_CONF"
1753 fi
1754
1755 # ------- Configurations -------
1756 if [ -n "$taboo_ports$taboo_ports_form2" ]
1757 then
1758         echo "INFO: (Re-)installation of the following ports are avoided as taboo:"
1759         echo "----------------------------------------"
1760         [ ! -e "${DBDIR}"/taboo.list ] || cat "${DBDIR}"/taboo.list
1761         echo "----------------------------------------"
1762         echo
1763 fi
1764
1765 if [ ! -e "${DBDIR}/COMPLETE_PARSE_OPTION_TARGET_PORTS" ]
1766 then
1767         rm -f "${DBDIR}/target_dependent_ports.specified" "${DBDIR}/target_required_ports.specified"
1768         register_globs_only_installed "$target_dependent_ports" "$target_dependent_ports_form2" > ${DBDIR}/target_dependent_ports.specified
1769         register_globs_only_installed "$target_required_ports" "$target_required_ports_form2" > ${DBDIR}/target_required_ports.specified
1770         touch "${DBDIR}/COMPLETE_PARSE_OPTION_TARGET_PORTS"
1771 fi
1772 if [ -n "$target_dependent_ports$target_dependent_ports_form2$target_required_ports$target_required_ports_form2" ]
1773 then
1774         echo "INFO: Operations will be applied only to the targets:"
1775         if [ `cat "${DBDIR}"/target_dependent_ports.specified | wc -l` -gt 0 -a `cat "${DBDIR}"/target_required_ports.specified | wc -l` -gt 0 ]
1776         then
1777                 echo "----------------------------------------"
1778                 cat "${DBDIR}"/target_dependent_ports.specified
1779                 echo "----------------------------------------"
1780                 echo "and their dependents;"
1781                 echo "----------------------------------------"
1782                 cat "${DBDIR}"/target_required_ports.specified
1783                 echo "----------------------------------------"
1784                 echo "and their requirements."
1785                 echo
1786         elif [ `cat "${DBDIR}"/target_dependent_ports.specified | wc -l` -gt 0 ]
1787         then
1788                 echo "----------------------------------------"
1789                 cat "${DBDIR}"/target_dependent_ports.specified
1790                 echo "----------------------------------------"
1791                 echo "and their dependents."
1792                 echo
1793         elif [ `cat "${DBDIR}"/target_required_ports.specified | wc -l` -gt 0 ]
1794         then
1795                 echo "----------------------------------------"
1796                 cat "${DBDIR}"/target_required_ports.specified
1797                 echo "----------------------------------------"
1798                 echo "and their requirements."
1799                 echo
1800         else
1801                 echo  "ERROR: Target ports are specified but none of them is valid." >&2
1802                 exit 1
1803         fi
1804 fi
1805
1806 # Parse configuration file
1807 if [ ! -e "${DBDIR}/COMPLETE_PARSE_CONF" ]
1808 then
1809         echo "Start to parse configuration file [${APPNAME}.conf] at `timestamp`"
1810         (
1811                 set -e
1812                 _CONFVARS='ENV ALT_MOVED HOLD TABOO REPLACE_FROM REPLACE_TO MARG_TARGET MARG_DEF MENV_TARGET MENV_DEF BEFOREBUILD BEFOREDEINSTALL AFTERINSTALL'
1813                 for item in ${_CONFVARS}
1814                 do
1815                         set | grep -e "^${item}_" | cut -d = -f 1 | sed 's/^/unset /'
1816                 done > ${TMPDIR}/unsetvars.sh
1817                 . "${TMPDIR}"/unsetvars.sh
1818                 . "${DBDIR}"/setup.conf
1819                 for item in ${_CONFVARS}
1820                 do
1821                         set | grep -e "^${item}_" | sed 's/^/_CONF_/'
1822                 done > ${DBDIR}/confvars.sh
1823         ) || { echo "ERROR: Invalid syntax in [${CONFFILE}]" >&2; exit 1; }
1824         touch "${DBDIR}/COMPLETE_PARSE_CONF"
1825 fi
1826 . "${DBDIR}/confvars.sh"
1827
1828 if [ ! -e "${DBDIR}/COMPLETE_REFLECTCONF_1" ]
1829 then
1830         echo "Starting to reflect settings of replacement defined in the configuration file at `timestamp`"
1831         echo PORTSDIR=${_CONF_ENV_PORTSDIR:-${PORTSDIR}} > "${DBDIR}/setenv.sh"
1832         echo DISTDIR=${_CONF_ENV_DISTDIR:-${DISTDIR:-${PORTSDIR}/distfiles}} >> "${DBDIR}/setenv.sh"
1833         
1834         if [ ! -e "${DBDIR}/COMPLETE_REFLECTCONF_ALT_MOVED" ]
1835         then
1836                 echo "-- ALT_MOVED_*"
1837                 cp -p "${PORTS_MOVED_DB}" "${TMPDIR}/MOVED.conflist"
1838                 set | grep -e '^_CONF_ALT_MOVED_' | cut -d = -f 1 | while read var
1839                 do
1840                         eval movedsb_path=\${$var}
1841                         cat "$movedsb_path" >> ${DBDIR}/MOVED.conflist
1842                 done
1843                 touch "${DBDIR}/COMPLETE_REFLECTCONF_ALT_MOVED"
1844         fi
1845         if [ "${DBDIR}/MOVED.conflist" -nt "${PORTS_MOVED_DB}" ]
1846         then
1847                 PORTS_MOVED_DB=${DBDIR}/MOVED.conflist
1848         fi
1849         
1850         build_conflist_target_list HOLD
1851         build_conflist_target_list TABOO
1852         combine_lists TABOO_PORTS.conflist taboo.list taboo.all.list
1853         
1854         if [ ! -e "${DBDIR}/COMPLETE_REFLECTCONF_REPLACE" ]
1855         then
1856                 echo "-- REPLACE_*"
1857                 cp /dev/null "${DBDIR}/REPLACE.grep_from_pattern.conflist"
1858                 cp /dev/null "${DBDIR}/REPLACE.replace_pattern.conflist"
1859                 set | grep -e '^_CONF_REPLACE_FROM_' | cut -d = -f 1 | while read var
1860                 do
1861                         eval glob_pattern=\${$var}
1862                         eval to=\${`echo $var | sed 's/^_CONF_REPLACE_FROM_/_CONF_REPLACE_TO_/'`}
1863                         expand_glob_pattern_to_origins "$glob_pattern" yes > ${TMPDIR}/origins.2.tmp || :
1864                         if [ `cat "${TMPDIR}/origins.2.tmp" | wc -l` -eq 0 ]
1865                         then
1866                                 echo "WARNING: Original package to be replaced [$glob_pattern] is obsolete." >&2
1867                                 echo "      If still required, use a pattern for port origins instead." >&2
1868                                 continue
1869                         fi
1870                         str_escape_regexp_filter < ${TMPDIR}/origins.2.tmp | sed "s|^|^|; s|$|$|" >> ${DBDIR}/REPLACE.grep_from_pattern.conflist
1871
1872                         if [ -z "$to" -o "$to" = delete ]
1873                         then
1874                                 to=
1875                         else
1876                                 [ -d "${PORTSDIR}/$to" ] || echo "WARNING: replacement port [$to] is obsolete" >&2
1877                         fi
1878                         str_escape_regexp_filter < ${TMPDIR}/origins.2.tmp | sed "s|^|s:^|; s|$|$:$to:|" >> ${DBDIR}/REPLACE.replace_pattern.conflist
1879                 done
1880                 touch "${DBDIR}/COMPLETE_REFLECTCONF_REPLACE"
1881         fi
1882         touch "${DBDIR}/COMPLETE_REFLECTCONF_1"
1883 fi
1884 . "${DBDIR}/setenv.sh"
1885
1886 if [ ! -e "${DBDIR}/COMPLETE_REFLECTCONF_2" ]
1887 then
1888         echo "Starting to reflect settings for each port defined in the configuration file at `timestamp`"
1889         build_conflist_target_val_pair MARG TARGET DEF
1890         build_conflist_target_val_pair MENV TARGET DEF
1891         build_conflist_target_val_pair BEFOREBUILD TARGET COMMAND
1892         build_conflist_target_val_pair BEFOREDEINSTALL TARGET COMMAND
1893         build_conflist_target_val_pair AFTERINSTALL TARGET COMMAND
1894         touch "${DBDIR}/COMPLETE_REFLECTCONF_2"
1895         echo
1896 fi
1897
1898 # ------- Database construction -------
1899
1900 # Target ports
1901 if [ ! -e "${DBDIR}/COMPLETE_INSTALLED_PORTS" ]
1902 then
1903         echo "Starting to collect installed packages at `timestamp`"
1904         pkg_info_qoa 2> /dev/null > ${DBDIR}/installed_ports
1905         str_escape_regexp_filter < "${DBDIR}/installed_ports" | sed 's/^/^/; s/$/$/' > ${DBDIR}/installed_ports.grep_pattern
1906         touch "${DBDIR}/COMPLETE_INSTALLED_PORTS"
1907         echo
1908 fi
1909
1910 if [ ! -e "${DBDIR}/COMPLETE_TARGETS" ]
1911 then
1912         echo "Starting to check newly installing ports at `timestamp`"
1913         cp "${DBDIR}/installed_ports" "${DBDIR}/target_ports"
1914         cat "${DBDIR}/target_dependent_ports.specified" "${DBDIR}/target_required_ports.specified" 2> /dev/null | sort -u | add_lines_if_new "${DBDIR}"/target_ports
1915         touch "${DBDIR}/COMPLETE_TARGETS"
1916         echo
1917 elif [ -e "${DBDIR}/REQUIRE_CHK_NEW_TARGET" ]
1918 then
1919         echo "Starting to check newly installing ports at `timestamp`"
1920         cp "${DBDIR}/target_ports" "${DBDIR}/target_ports.new"
1921         sort -u "${DBDIR}/target_dependent_ports.specified" "${DBDIR}/target_required_ports.specified" | add_lines_if_new "${DBDIR}"/target_ports.new
1922         if [ `cat "${DBDIR}/target_ports" | wc -l` -ne `cat "${DBDIR}/target_ports.new" | wc -l` ]
1923         then
1924                 echo "WARNING: The temporal database will be refreshed so as to reinstall the all failed ports and their dependents."
1925                 rm -f "${DBDIR}/COMPLETE_COLLECED_ALL_DEPENDENCIES" \
1926                         "${DBDIR}/COMPLETE_DISTFILES_LIST" \
1927                         "${DBDIR}/COMPLETE_CONVERT_REQUIRES_LIST" \
1928                         "${DBDIR}/COMPLETE_INSPECT_DEPENDENTS" \
1929                         "${DBDIR}/COMPLETE_COPY_DEPENDENCY_TMPFILES" \
1930                         "${DBDIR}/COMPLETE_ORDERED_ALL_DEPENDENCIES" \
1931                         "${DBDIR}/COMPLETE_CHECKED_UNSATISFIED_DEPENDENCIES" \
1932                         "${DBDIR}/COMPLETE_REFLECTCONF_2"
1933         fi
1934         echo
1935 fi
1936 rm -f "${DBDIR}/REQUIRE_CHK_NEW_TARGET"
1937
1938 # Inspection of all dependencies
1939 if [ ! -e "${DBDIR}/COMPLETE_COLLECED_ALL_DEPENDENCIES" ]
1940 then
1941         echo "Starting to inspect dependencies of the all installed packages at `timestamp`"
1942         [ -z "$target_dependent_ports$target_dependent_ports_form2$target_required_ports$target_required_ports_form2" ] || \
1943                 echo "INFO: Ports irrelevant to the targets are also inspected in order to get complete information."
1944         [ -d "${DBDIR}/requires" ] || mkdir -p "${DBDIR}/requires"
1945         touch "${DBDIR}/moved_or_lost.list"
1946         touch "${DBDIR}/target.inspected.list"
1947         if [ -f "${DBDIR}/target_ports.remain" ]
1948         then
1949                 echo "INFO: Restarting from the previously terminated point"
1950         else
1951                 cp -p "${DBDIR}/target_ports" "${DBDIR}/target_ports.remain"
1952         fi
1953         cp "${DBDIR}/target_ports.remain" "${TMPDIR}/target_ports"
1954         DEPTH_INDEX='--'
1955         nlines=`cat "${TMPDIR}/target_ports" | wc -l`
1956         iline=1
1957         while [ $iline -le $nlines ]
1958         do
1959                 origin=`sed -n ${iline}p "${TMPDIR}/target_ports"`
1960                 iline=$(($iline+1))
1961                 inspect_dependencies "$origin"
1962                 continue
1963         done
1964         touch "${DBDIR}/REPLACE.complete_replace_pattern.tmp"
1965         sort "${DBDIR}/REPLACE.complete_replace_pattern.tmp" | uniq > ${DBDIR}/REPLACE.complete_replace_pattern
1966         touch "${DBDIR}/COMPLETE_COLLECED_ALL_DEPENDENCIES"
1967         echo
1968 fi
1969
1970 # Inspection of all required distfiles
1971 if [ ! -e "${DBDIR}/COMPLETE_DISTFILES_LIST" -a $keep_distfiles = no ]
1972 then
1973         echo "Starting to summarize distfiles list at `timestamp`"
1974         sort "${DBDIR}/distfiles.list" 2> /dev/null | uniq | str_escape_regexp_filter | sed 's|^|/|; s|$|$|' > ${DBDIR}/distfiles.grep.pattern || :
1975         touch "${DBDIR}/COMPLETE_DISTFILES_LIST"
1976         echo
1977 fi
1978
1979 # Convert requires-lists to actual ones
1980 if [ ! -e "${DBDIR}/COMPLETE_CONVERT_REQUIRES_LIST" ]
1981 then
1982         echo "Starting conversion of requires-lists to actual ones at `timestamp`"
1983         if [ -f "${DBDIR}/convert_requires_lists.remain" ]
1984         then
1985                 echo "INFO: Restarting from the previously terminated point"
1986         else
1987                 find "${DBDIR}/requires" -depth 2 -type d > ${DBDIR}/convert_requires_lists.remain
1988         fi
1989         cp "${DBDIR}/convert_requires_lists.remain" "${TMPDIR}/convert_requires_lists"
1990         while read dbpath
1991         do
1992                 portname=`basename "$dbpath"`
1993                 catpath=`dirname "$dbpath"`
1994                 catname=`basename "$catpath"`
1995                 origin=$catname/$portname
1996                 sed -E -f "${DBDIR}/REPLACE.complete_replace_pattern" "$dbpath/requires" | grep -v '^$' | sort | uniq > $dbpath/requires.new
1997                 mv "$dbpath/requires.new" "$dbpath/requires"
1998                 sed -i '' 1d "${DBDIR}/convert_requires_lists.remain"
1999         done < ${TMPDIR}/convert_requires_lists
2000         touch "${DBDIR}/COMPLETE_CONVERT_REQUIRES_LIST"
2001         echo
2002 fi
2003
2004 # Inspection of dependents
2005 if [ ! -e "${DBDIR}/COMPLETE_INSPECT_DEPENDENTS" ]
2006 then
2007         echo "Starting inspection of dependents at `timestamp`"
2008         if [ -f "${DBDIR}/inspect_dependent.remain" ]
2009         then
2010                 echo "INFO: Restarting from the previously terminated point"
2011         else
2012                 find "${DBDIR}/requires" -depth 2 -type d > ${DBDIR}/inspect_dependent.remain
2013         fi
2014         cp "${DBDIR}/inspect_dependent.remain" "${TMPDIR}/inspect_dependent"
2015         while read dbpath
2016         do
2017                 portname=`basename "$dbpath"`
2018                 catpath=`dirname "$dbpath"`
2019                 catname=`basename "$catpath"`
2020                 origin=$catname/$portname
2021                 sed "s|^|${DBDIR}/requires/|; s|$|/dependents|" "$dbpath/requires" | add_a_line_to_files_if_new "$origin"
2022                 sed -i '' 1d "${DBDIR}/inspect_dependent.remain"
2023         done < ${TMPDIR}/inspect_dependent
2024         touch "${DBDIR}/COMPLETE_INSPECT_DEPENDENTS"
2025         echo
2026 fi
2027
2028 # Preparation of matching patterns of dependencies
2029 if [ ! -e "${DBDIR}/COMPLETE_PREPARATION_OF_MATCHING_PATTERNS_OF_DEPENDENCIES" ]
2030 then
2031         echo "Starting preparation of matching patterns of dependencies at `timestamp`"
2032         if [ -f "${DBDIR}/prepare_matching_patterns_dependencies.remain" ]
2033         then
2034                 echo "INFO: Restarting from the previously terminated point"
2035         else
2036                 find "${DBDIR}/requires" -depth 2 -type d > ${DBDIR}/prepare_matching_patterns_dependencies.remain
2037         fi
2038         cp "${DBDIR}/prepare_matching_patterns_dependencies.remain" "${DBDIR}/prepare_matching_patterns_dependencies"
2039         while read dbpath
2040         do
2041                 portname=`basename "$dbpath"`
2042                 catpath=`dirname "$dbpath"`
2043                 catname=`basename "$catpath"`
2044                 origin=$catname/$portname
2045                 [ ! -e "${DBDIR}/requires/$origin/dependents" ] || str_escape_regexp_filter < ${DBDIR}/requires/$origin/dependents | sed 's/^/^/;s/$/$/' > ${DBDIR}/requires/$origin/dependents.pattern
2046                 [ ! -e "${DBDIR}/initial/$origin/dependents" ] || str_escape_regexp_filter < ${DBDIR}/initial/$origin/dependents | sed 's/^/^/;s/$/$/' > ${DBDIR}/initial/$origin/dependents.pattern
2047                 [ ! -e "${DBDIR}/requires/$origin/requires" ] || str_escape_regexp_filter < ${DBDIR}/requires/$origin/requires | sed 's/^/^/;s/$/$/' > ${DBDIR}/requires/$origin/requires.pattern
2048                 [ ! -e "${DBDIR}/initial/$origin/requires" ] || str_escape_regexp_filter < ${DBDIR}/initial/$origin/requires | sed 's/^/^/;s/$/$/' > ${DBDIR}/initial/$origin/requires.pattern
2049                 chk_if_target currentorigin "$origin"
2050                 sed -i '' 1d "${DBDIR}/prepare_matching_patterns_dependencies.remain"
2051         done < ${DBDIR}/prepare_matching_patterns_dependencies
2052         touch "${DBDIR}/COMPLETE_PREPARATION_OF_MATCHING_PATTERNS_OF_DEPENDENCIES"
2053         echo
2054 fi
2055
2056 # Preparation of matching patterns of obsolete ports to be deleted
2057 if [ ! -e "${DBDIR}/COMPLETE_PREPARATION_OF_MATCHING_PATTERNS_OF_OBSOLETE_PORTS" ]
2058 then
2059         echo "Starting preparation of matching patterns of obsolete ports to be deleted at `timestamp`"
2060         if [ -f "${DBDIR}/prepare_matching_patterns_obsolete_ports.remain" ]
2061         then
2062                 echo "INFO: Restarting from the previously terminated point"
2063         else
2064                 cp -p "${DBDIR}/moved_or_lost.list" "${DBDIR}/prepare_matching_patterns_obsolete_ports.remain"
2065         fi
2066         cp "${DBDIR}/prepare_matching_patterns_obsolete_ports.remain" "${DBDIR}/prepare_matching_patterns_obsolete_ports"
2067         while read origin
2068         do
2069                 chk_if_target currentorigin "$origin"
2070                 sed -i '' 1d "${DBDIR}/prepare_matching_patterns_obsolete_ports.remain"
2071         done < ${DBDIR}/prepare_matching_patterns_obsolete_ports
2072         touch "${DBDIR}/COMPLETE_PREPARATION_OF_MATCHING_PATTERNS_OF_OBSOLETE_PORTS"
2073         echo
2074 fi
2075
2076 # Inspection of necessary updates
2077 if [ ! -e "${DBDIR}/COMPLETE_NECESSARY_UPDATES" ]
2078 then
2079         echo "Starting inspection of necessary updates at `timestamp`"
2080         if [ -f "${DBDIR}/necessary_updates.remain" ]
2081         then
2082                 echo "INFO: Restarting from the previously terminated point"
2083         else
2084                 find "${DBDIR}/requires" -depth 2 -type d > ${DBDIR}/necessary_updates.remain
2085         fi
2086         cp "${DBDIR}/necessary_updates.remain" "${TMPDIR}/necessary_updates"
2087         while read dbpath
2088         do
2089                 portname=`basename "$dbpath"`
2090                 catpath=`dirname "$dbpath"`
2091                 catname=`basename "$catpath"`
2092                 origin=$catname/$portname
2093                 if [ -e "${DBDIR}/requires/$origin/new_version" ]
2094                 then
2095                         touch "${DBDIR}/requires/$origin/necessary_update"
2096                         if [ -e "${DBDIR}/requires/$origin/dependents" ]
2097                         then
2098                                 while read origin_dependent
2099                                 do
2100                                         touch "${DBDIR}/requires/$origin_dependent/necessary_update"
2101                                 done < ${DBDIR}/requires/$origin/dependents
2102                         fi
2103                 fi
2104                 sed -i '' 1d "${DBDIR}/necessary_updates.remain"
2105         done < ${TMPDIR}/necessary_updates
2106         touch "${DBDIR}/COMPLETE_NECESSARY_UPDATES"
2107         echo
2108 fi
2109
2110 # Copying dependencies for preparation
2111 if [ ! -e "${DBDIR}/COMPLETE_COPY_DEPENDENCY_TMPFILES" ]
2112 then
2113         echo "Starting preparation for order of dependencies at `timestamp`"
2114         find "${DBDIR}/requires" -depth 3 -name requires -exec cp -p {} {}.remained \;
2115         touch "${DBDIR}/COMPLETE_COPY_DEPENDENCY_TMPFILES"
2116         echo
2117 fi
2118
2119 # Clean up of reinstallation status for preparation
2120 if [ -e "${DBDIR}/MODE_REDO" -a ! -e "${DBDIR}/COMPLETE_CLEANUP_REINST_STATUS" ]
2121 then
2122         echo "Starting preparation for order of dependencies at `timestamp`"
2123         find "${DBDIR}/requires" -depth 3 -type d -name status -exec rm -rf {} \; -exec mkdir {} \;
2124         touch "${DBDIR}/COMPLETE_CLEANUP_REINST_STATUS"
2125         echo
2126 fi
2127
2128 # Order the ports considering dependencies
2129 if [ ! -e "${DBDIR}/COMPLETE_ORDERED_ALL_DEPENDENCIES" ]
2130 then
2131         echo "Starting ordering of dependencies at `timestamp`"
2132         [ ! -f "${DBDIR}/reinst_order.list.tmp" ] || echo "INFO: Restarting from the previously terminated point"
2133         touch "${DBDIR}/reinst_order.list.tmp"
2134         cd "${DBDIR}/requires"
2135         cat > ${TMPDIR}/order_dependencies.awk << eof
2136 BEGIN {
2137         it = 0;
2138         i = 0;
2139 }
2140 {
2141         if (NF == 0)
2142         {
2143                 i = 0;
2144         }
2145         else
2146         {
2147                 if (i == 0)
2148                 {
2149                         target = \$0;
2150                         sub (/\/requires\.remained$/, "", target);
2151                         sub (/^\.\//, "", target);
2152                         srcikey[it] = target;
2153                         srckeyi[target] = it;
2154                         it++;
2155                 }
2156                 else
2157                 {
2158                         src[it-1,i-1] = \$0;
2159                         srcimax[it-1] = srcsize[it-1] = i;
2160                 }
2161                 i++;
2162         }
2163 }
2164 END {
2165         ntargets = it;
2166         norder = 0;
2167         order_str = "";
2168         icycle = 0;
2169         lf_order_str = "";
2170         while (1)
2171         {
2172                 is_operated = 0;
2173                 for (it = 0; it < ntargets; it++)
2174                 {
2175                         if (!(it in srcikey)) continue;
2176                         if (srcsize[it] > 0) continue;
2177                         is_operated = 1;
2178                         target = srcikey[it];
2179 #                       print "[" icycle "]-- " target;
2180                         delete srcikey[it];
2181                         order[norder++] = target;
2182                         order_str = order_str lf_order_str;
2183                         order_str = sprintf ("%s%s", order_str, target);
2184                         lf_order_str = "\n";
2185                         for (jt = 0; jt < ntargets; jt++)
2186                         {
2187                                 for (j = 0; j < srcimax[jt]; j++)
2188                                 {
2189                                         if ((jt,j) in src && src[jt,j] == target)
2190                                         {
2191                                                 delete src[jt,j];
2192                                                 srcsize[jt]--;
2193                                                 break;
2194                                         }
2195                                 }
2196                         }
2197                 }
2198                 if (is_operated == 0) break;
2199                 icycle++;
2200         }
2201         reinst_order_list = sprintf ("%s%s", ENVIRON["DBDIR"], "/reinst_order.list.tmp");
2202         print order_str > reinst_order_list;
2203         unsatisfied = "";
2204         for (it = 0; it < ntargets; it++)
2205         {
2206                 if (srcsize[it] == 0) continue;
2207                 reqs = "";
2208                 sp_reqs = "";
2209                 for (i = 0; i < srcimax[it]; i++)
2210                 {
2211                         if ((it,i) in src)
2212                         {
2213                                 reqs = reqs ", " src[it,i];
2214                                 sp_reqs = ", ";
2215                         }
2216                 }
2217                 unsatisfied = sprintf ("%s%s [%d] (%s)\n", unsatisfied, srcikey[it], srcsize[it], reqs);
2218         }
2219         if (unsatisfied != "")
2220         {
2221                 unsatisfied_list = sprintf ("%s%s", ENVIRON["DBDIR"], "/unsatisfied.list");
2222                 print unsatisfied > unsatisfied_list;
2223                 exit 1;
2224         }
2225 }
2226 eof
2227         find . -depth 3 -name requires.remained -exec echo {} \; -exec cat {} \; -exec echo \; | \
2228                 env DBDIR=${DBDIR} awk -f "${TMPDIR}"/order_dependencies.awk || { \
2229                         echo "ERROR: Unsatisfied dependencies are remained" >&2
2230                         cat "${DBDIR}/unsatisfied.list"
2231                         echo "*** Aborted by ${APPNAME}"
2232                         echo "The ports tree seems broken. You might have caught an incomplete version."
2233                         echo "You are encouraged to update the ports tree by portsnap(8)."
2234                         echo "Then execute"
2235                         echo " ${APPNAME} clean"
2236                         echo "before restart."
2237                         terminate_process ()
2238                         {
2239                         }
2240                         exit 1
2241                 }
2242         grep -v '^$' "${DBDIR}/reinst_order.list.tmp" > "${DBDIR}/reinst_order.list" || :
2243         touch "${DBDIR}/COMPLETE_ORDERED_ALL_DEPENDENCIES"
2244         rm -f "${TMPDIR}/targets"
2245         echo
2246 fi
2247
2248 # Deinstallation of obsolete packages
2249 if [ ! -e "${DBDIR}/COMPLETE_LIST_DEINST_OBS_PKGS" ]
2250 then
2251         echo "Starting to compose a list of deinstallation of obsolete packages at `timestamp`"
2252         while read origin
2253         do
2254                 origin_ptn=`str_escape_regexp ${origin}`
2255                 [ `grep -m 1 -E "^${origin_ptn}$" "${DBDIR}/HOLD_PORTS.conflist" 2> /dev/null | wc -l` -gt 0 ] || echo $origin
2256         done < ${DBDIR}/moved_or_lost.list > ${DBDIR}/moved_or_lost.actual.list.tmp
2257         mv "${DBDIR}"/moved_or_lost.actual.list.tmp "${DBDIR}"/moved_or_lost.actual.list
2258         touch "${DBDIR}/COMPLETE_LIST_DEINST_OBS_PKGS"
2259         echo
2260 fi
2261
2262 # ------- Main operations -------
2263
2264 if [ ! -e "${DBDIR}/COMPLETE_PREPARATION" ]
2265 then
2266         touch "${DBDIR}/COMPLETE_PREPARATION"
2267 fi
2268
2269 if [ "$command" = prepare ]
2270 then
2271         fold -s << eof
2272 Done (skipped reinstallation) at `timestamp`
2273
2274  You can restart this process from the aborted/terminated point by executing without options or arguments as:
2275   ${APPNAME}
2276 eof
2277         terminate_process ()
2278         {
2279         }
2280         exit
2281 fi
2282
2283 terminate_process ()
2284 {
2285         terminate_process_common
2286         terminate_process ()
2287         {
2288         }
2289 }
2290
2291 # Deinstallation of obsolete packages
2292 if [ ! -e "${DBDIR}/COMPLETE_DEINST_OBS_PKGS" ]
2293 then
2294         _MSG_CURRENT_STAGE_general="deinstallation of obsolete packages"
2295         _MSG_CURRENT_STAGE=${_MSG_CURRENT_STAGE_general}
2296         echo "Starting deinstallation of obsolete packages at `timestamp`"
2297         [ -d "${DBDIR}/backup_obsolete" ] || mkdir -p "${DBDIR}/backup_obsolete"
2298         [ -d "${DBDIR}/status_deinst" ] || mkdir -p "${DBDIR}/status_deinst"
2299         if [ `cat "${DBDIR}/moved_or_lost.list" | wc -l` -gt 0 ]
2300         then
2301                 if [ -f "${DBDIR}/moved_or_lost.list.remained" ]
2302                 then
2303                         echo "INFO: Restarting from the previously terminated point"
2304                 else
2305                         cp -p "${DBDIR}/moved_or_lost.list" "${DBDIR}/moved_or_lost.list.remained"
2306                 fi
2307                 cp -p "${DBDIR}/moved_or_lost.list.remained" "${TMPDIR}/moved_or_lost.tmp"
2308                 nlines=`cat "${TMPDIR}/moved_or_lost.tmp" | wc -l`
2309                 iline=1
2310                 while [ $iline -le $nlines ]
2311                 do
2312                         origin=`sed -n ${iline}p "${TMPDIR}/moved_or_lost.tmp"`
2313                         iline=$(($iline+1))
2314                         currentpkg=`pkg_info_qO "$origin" 2> /dev/null`
2315                         [ -n "$currentpkg" ] || continue
2316                         chk_if_target currentorigin "$origin"
2317                         if [ -z "${currentorigin_is_relevant}" ]
2318                         then
2319                                 echo "-- (Skipping an irrelevant package for obsolete port $origin as $currentpkg)"
2320                                 continue
2321                         fi
2322                         origin_ptn=`str_escape_regexp ${origin}`
2323                         if [ `grep -m 1 -E "^${origin_ptn}$" "${DBDIR}/HOLD_PORTS.conflist" 2> /dev/null | wc -l` -gt 0 ]
2324                         then
2325                                 echo "-- (Skipping a hold package for obsolete port $origin as $currentpkg)"
2326                                 continue
2327                         fi
2328                         _MSG_CURRENT_STAGE=${_MSG_CURRENT_STAGE_general}
2329                         echo "========== Starting deinstallation process for obsolete port $origin as $currentpkg =========="
2330                         if [ -z "${currentorigin_is_all}" -a -n "${currentorigin_is_relevant}" ]
2331                         then
2332                                 [ -z "${currentorigin_is_target}" ] || echo "(Target port)"
2333                                 [ -z "${currentorigin_is_dependent}" ] || echo "(Dependent of the target port(s))"
2334                                 [ -z "${currentorigin_is_required}" ] || echo "(Requirement of the target port(s))"
2335                                 [ -z "${currentorigin_is_former_dependent}" ] || echo "(Former dependent of the target port(s))"
2336                                 [ -z "${currentorigin_is_former_required}" ] || echo "(Former requirement of the target port(s))"
2337                         fi
2338                         echo "-- (Creating backup package for $origin as $currentpkg)"
2339                         tag=`echo $origin | sed 's|/|.|'`
2340                         if [ ! -e "${DBDIR}/status_deinst/$tag.backup" ]
2341                         then
2342                                 backup_pkg=`create_backup_pkg "$currentpkg" "${DBDIR}/backup_obsolete"` || :
2343                                 if [ -n "$backup_pkg" ]
2344                                 then
2345                                         echo "$backup_pkg" > ${DBDIR}/requires/$origin/backedup_pkgfile
2346                                 else
2347                                         echo "*** Continuating forcibly by keeping the installed package"
2348                                         continue
2349                                 fi
2350                                 touch "${DBDIR}/status_deinst/$tag.backup"
2351                         fi
2352                         echo "-- (Deleting package for $origin as $currentpkg)"
2353                         pkg_delete_f "$currentpkg" || { echo "*** Continuating forcibly by hoping success..."; continue; }
2354                         rm_a_line "$origin" "${DBDIR}/moved_or_lost.list.remained"
2355                         _MSG_CURRENT_STAGE=${_MSG_CURRENT_STAGE_general}
2356                         echo
2357                 done
2358         fi
2359         touch "${DBDIR}/COMPLETE_DEINST_OBS_PKGS"
2360         _MSG_CURRENT_STAGE=
2361         echo
2362 fi
2363
2364 # Reinstallation of remained ports
2365 [ ! -e "${DBDIR}/MODE_REDO" ] || rm -f "${DBDIR}/COMPLETE_REINSTALLATION" "${DBDIR}/COMPLETE_CLEANUP_OBSLETE_DISTFILES" "${DBDIR}/COMPLETE_REBUILD_PKGDB"
2366 [ `cat "${DBDIR}/reinst_order.list" | wc -l` -gt 0 ] || touch "${DBDIR}/COMPLETE_REINSTALLATION"
2367 if [ ! -e "${DBDIR}/COMPLETE_REINSTALLATION" ]
2368 then
2369         _MSG_CURRENT_STAGE_general="reinstallation"
2370         _MSG_CURRENT_STAGE=${_MSG_CURRENT_STAGE_general}
2371         echo "Starting reinstallation at `timestamp`"
2372         savedir=`pwd`
2373         mkdir "${TMPDIR}/backup"
2374         [ -d "${DBDIR}/backup_failure" ] || mkdir -p "${DBDIR}/backup_failure"
2375         if [ ! -e "${DBDIR}/MODE_REDO" -a -f "${DBDIR}/reinst_todo.list" ]
2376         then
2377                 echo "INFO: Restarting from the previously terminated point"
2378         else
2379                 cp -p "${DBDIR}/reinst_order.list" "${DBDIR}/reinst_todo.list"
2380         fi
2381         rm -f "${DBDIR}/MODE_REDO"
2382         cp -p "${DBDIR}/reinst_todo.list" "${TMPDIR}/reinst_todo.tmp"
2383         touch "${DBDIR}/failed.list"
2384         touch "${DBDIR}/success_but_dependencies_failed.list"
2385         touch "${DBDIR}/success.list"
2386         nlines_tot=$((`cat "${DBDIR}/reinst_order.list" | wc -l`))
2387         nlines=`cat "${TMPDIR}/reinst_todo.tmp" | wc -l`
2388         icount=$(($nlines_tot-$nlines))
2389         iline=1
2390         while [ $iline -le $nlines ]
2391         do
2392                 _MSG_CURRENT_STAGE=${_MSG_CURRENT_STAGE_general}
2393                 origin=`sed -n ${iline}p "${TMPDIR}/reinst_todo.tmp"`
2394                 iline=$(($iline+1))
2395                 icount=$(($icount+1))
2396                 MAKE_ARGS="FORCE_PKG_REGISTER=yes `[ $avoid_vulner = yes ] || echo DISABLE_VULNERABILITIES=yes` `cat "${DBDIR}/requires/$origin/MARG.conflist" 2> /dev/null || :`"
2397                 MAKE_ENVS=`cat "${DBDIR}/requires/$origin/MENV.conflist" 2> /dev/null || :`
2398                 counter="[$icount/$nlines_tot $(($icount*100/$nlines_tot))%]"
2399                 if [ -e "${DBDIR}"/requires/$origin/new_version ]
2400                 then
2401                         newpkg=`cat "${DBDIR}"/requires/$origin/new_version`
2402                 else
2403                         newpkg=
2404                 fi
2405                 currentpkg=`pkg_info_qO "$origin" 2> /dev/null || :`
2406                 if [ -n "$currentpkg" ]
2407                 then
2408                         origpkg=$currentpkg
2409                 else
2410                         origpkg=`cat "${DBDIR}/requires/$origin/backedup_version" 2> /dev/null || :`
2411                 fi
2412                 pkgtag=$origpkg
2413                 is_currentport_latest=no
2414                 [ -n "$pkgtag" ] || pkgtag=$newpkg
2415                 if [ -z "$pkgtag" ]
2416                 then
2417                         pkgtag='?'
2418                 
2419                 elif [ -n "$newpkg" -a "x$currentpkg" != "x$newpkg" ]
2420                 then
2421                         if [ -n "$currentpkg" ]
2422                         then
2423                                 pkgtag="$currentpkg => $newpkg"
2424                         else
2425                                 pkgtag="[new] $newpkg"
2426                         fi
2427                 else
2428                         is_currentport_latest=yes
2429                 fi
2430                 echo $pkgtag > ${DBDIR}/requires/$origin/pkgtag
2431                 position_msg="$origin ($pkgtag)"
2432                 if grep -m 1 -E "^`str_escape_regexp ${origin}`$" "${DBDIR}/success.list" 2> /dev/null > /dev/null
2433                 then
2434                         echo "========== $counter (Skipping an already reinstalled package for port $position_msg at `timestamp`) =========="
2435                         echo
2436                         rm_a_line "$origin" "${DBDIR}/reinst_todo.list"
2437                         continue
2438                 fi
2439                 if [ $skip_unchanged = yes -a $is_currentport_latest = yes ]
2440                 then
2441                         if [ ! -e "${DBDIR}/requires/$origin/necessary_update" ]
2442                         then
2443                                 echo "========== $counter (Skipping a port, $position_msg, because itself and the all of its requirements are already latest at `timestamp`) =========="
2444                                 echo
2445                                 rm_a_line "$origin" "${DBDIR}/reinst_todo.list"
2446                                 continue
2447                         fi
2448                 fi
2449                 if [ \( $skip_unchanged = no -a -e "${DBDIR}/requires/$origin/succeeded_once" \) -o \( $skip_unchanged = yes -a $is_currentport_latest = yes \) ]
2450                 then
2451                         if [ ! -e "${DBDIR}/requires/$origin/need_reinstall_due_to_updated_requirements" ]
2452                         then
2453                                 if [ ! -e "${DBDIR}/requires/$origin/failed_requirements.previous" ]
2454                                 then
2455                                         need_update=no
2456                                 else
2457                                         sort -u "${DBDIR}/requires/$origin/failed_requirements" > ${TMPDIR}/failed_requirements.new
2458                                         sort -u "${DBDIR}/requires/$origin/failed_requirements.previous" > ${TMPDIR}/failed_requirements.old
2459                                         if diff "${TMPDIR}/failed_requirements.old" "${TMPDIR}/failed_requirements.new" \
2460                                                 > ${TMPDIR}/failed_requirements.diff
2461                                         then
2462                                                 need_update=no
2463                                         elif grep -m 1 '^<' "${TMPDIR}/failed_requirements.diff" > /dev/null
2464                                         then
2465                                                 need_update=yes
2466                                         else
2467                                                 need_update=no
2468                                         fi
2469                                 fi
2470                                 if [ $need_update = no ]
2471                                 then
2472                                         echo "========== $counter (Skipping a port, $position_msg, because itself and the all of its requirements are already latest or left failed in update at `timestamp`) =========="
2473                                         echo
2474                                         add_a_line_if_new "$origin" "${DBDIR}/todo_after_requirements_succeed.list"
2475                                         rm_a_line "$origin" "${DBDIR}/reinst_todo.list"
2476                                         continue
2477                                 fi
2478                         fi
2479                 fi
2480                 chk_if_target currentorigin "$origin"
2481                 cp /dev/null "${TMPDIR}"/msg_if_target
2482                 if [ -z "${currentorigin_is_all}" ]
2483                 then
2484                         if [ -n "${currentorigin_is_relevant}" ]
2485                         then
2486                                 [ -z "${currentorigin_is_target}" ] || echo "(Target port)" > ${TMPDIR}/msg_if_target
2487                                 [ -z "${currentorigin_is_dependent}" ] || echo "(Dependent of the target port(s))" >> ${TMPDIR}/msg_if_target
2488                                 [ -z "${currentorigin_is_required}" ] || echo "(Requirement of the target port(s))" >> ${TMPDIR}/msg_if_target
2489                                 [ -z "${currentorigin_is_former_dependent}" ] || echo "(Former dependent of the target port(s))" >> ${TMPDIR}/msg_if_target
2490                                 [ -z "${currentorigin_is_former_required}" ] || echo "(Former requirement of the target port(s))" >> ${TMPDIR}/msg_if_target
2491                         else
2492                                 echo "========== $counter (Skipping an irrelevant package for port $position_msg at `timestamp`) =========="
2493                                 echo
2494                                 rm_a_line "$origin" "${DBDIR}/reinst_todo.list"
2495                                 continue
2496                         fi
2497                 fi
2498                 if grep -m 1 -E "^`str_escape_regexp ${origin}`$" "${DBDIR}/HOLD_PORTS.conflist" 2> /dev/null > /dev/null
2499                 then
2500                         echo "========== $counter (Skipping a hold package for port $position_msg at `timestamp`) =========="
2501                         cat ${TMPDIR}/msg_if_target
2502                         echo
2503                         rm_a_line "$origin" "${DBDIR}/reinst_todo.list"
2504                         continue
2505                 fi
2506                 if grep -m 1 -E "^`str_escape_regexp $origin`$" "${DBDIR}/taboo.all.list" 2> /dev/null > /dev/null
2507                 then
2508                         echo "========== $counter (Ignored a taboo port $position_msg at `timestamp`) =========="
2509                         cat ${TMPDIR}/msg_if_target
2510                         echo
2511                         rm_a_line "$origin" "${DBDIR}/reinst_todo.list"
2512                         continue
2513                 fi
2514                 if grep -m 1 -E "^`str_escape_regexp $origin`$" "${DBDIR}/manually_done.list" 2> /dev/null > /dev/null
2515                 then
2516                         echo "========== $counter (Marking a manually-done port $position_msg as success at `timestamp`) =========="
2517                         cat ${TMPDIR}/msg_if_target
2518                         echo
2519                         rm_a_line "$origin" "${DBDIR}/reinst_todo.list"
2520                         continue
2521                 fi
2522                 if [ -e "${DBDIR}/requires/$origin/SUPPRESSED" ]
2523                 then
2524                         echo "========== $counter (Skipping a suppressed port $position_msg as success at `timestamp`) =========="
2525                         cat ${TMPDIR}/msg_if_target
2526                         echo
2527                         rm_a_line "$origin" "${DBDIR}/reinst_todo.list"
2528                         continue
2529                 fi
2530                 if [ -e "${DBDIR}/requires/$origin/installed_version" ]
2531                 then
2532                         insttarget=reinstall
2533                         instdesc='a reinstallation'
2534                 else
2535                         insttarget=install
2536                         instdesc='an installation'
2537                 fi
2538                 _MSG_CURRENT_STAGE="$instdesc process for $position_msg $counter"
2539                 echo "========== $counter Starting $instdesc process for $position_msg at `timestamp` =========="
2540                 cat ${TMPDIR}/msg_if_target
2541                 cd "${PORTSDIR}/$origin"
2542                 if [ -e "${DBDIR}/requires/$origin/status/in_build" ]
2543                 then
2544                         echo "(Restarting the previously terminated build process...)"
2545                         flag_restarted_build=yes
2546                 else
2547                         touch "${DBDIR}/requires/$origin/status/in_build"
2548                         flag_restarted_build=no
2549                 fi
2550                 if [ -e "${DBDIR}/requires/$origin/BEFOREBUILD.conflist" -a ! -e "${DBDIR}/requires/$origin/status/COMPLETE_BEFOREBUILD" ]
2551                 then
2552                         echo "-- BEFOREBUILD operations (start)"
2553                         sh -e "${DBDIR}/requires/$origin/BEFOREBUILD.conflist" || \
2554                         {
2555                                 echo "ERROR: while BEFOREBUILD operations for ${PORTSDIR}/$position_msg." >&2
2556                                 echo 'BEFOREBUILD operations' > ${DBDIR}/requires/$origin/note_failtre
2557                                 record_failure $origin noclean
2558                                 rm_a_line "$origin" "${DBDIR}/reinst_todo.list"
2559                                 cmt_fail_reinst "$origin"
2560                                 continue
2561                         }
2562                         echo "-- BEFOREBUILD operations (end)"
2563                         touch "${DBDIR}/requires/$origin/status/COMPLETE_BEFOREBUILD"
2564                 fi
2565                 if [ ! -e "${DBDIR}/requires/$origin/status/COMPLETE_CLEAN_BEFORE_BUILD" ]
2566                 then
2567                         env ${MAKE_ENVS} make clean ${MAKE_ARGS} || \
2568                         {
2569                                 echo "ERROR: Check the permission of directory ${PORTSDIR}/$position_msg." >&2
2570                                 echo 'clean before build' > ${DBDIR}/requires/$origin/note_failtre
2571                                 record_failure $origin noclean
2572                                 rm_a_line "$origin" "${DBDIR}/reinst_todo.list"
2573                                 cmt_fail_reinst "$origin"
2574                                 continue
2575                         }
2576                         echo
2577                         touch "${DBDIR}/requires/$origin/status/COMPLETE_CLEAN_BEFORE_BUILD"
2578                 fi
2579                 if [ ! -e "${DBDIR}/requires/$origin/status/COMPLETE_FETCH" ]
2580                 then
2581                         if [ ! -e "${DBDIR}/requires/$origin/status/FAILED_FETCH" ]
2582                         then
2583                                 if env ${MAKE_ENVS} make checksum ${MAKE_ARGS}
2584                                 then
2585                                         :
2586                                 else
2587                                         touch "${DBDIR}/requires/$origin/status/FAILED_FETCH"
2588                                 fi
2589                         fi
2590                         if [ -e "${DBDIR}/requires/$origin/status/FAILED_FETCH" ]
2591                         then
2592                                 echo "WARNING: Refetching distfiles for ${PORTSDIR}/$position_msg." >&2
2593 #                               if [ ! -e "${DBDIR}/requires/$origin/status/COMPLETE.FAILED_FETCH.DISTCLEAN" ]
2594 #                               then
2595 #                                       env ${MAKE_ENVS} make distclean NOCLEANDEPENDS=yes ${MAKE_ARGS} || \
2596 #                                       {
2597 #                                               echo "ERROR: Failed in distclean for ${PORTSDIR}/$position_msg." >&2
2598 #                                               echo 'distclean for refetch' > ${DBDIR}/requires/$origin/note_failtre
2599 #                                               record_failure $origin
2600 #                                               rm_a_line "$origin" "${DBDIR}/reinst_todo.list"
2601 #                                               cmt_fail_reinst "$origin"
2602 #                                               continue
2603 #                                       }
2604 #                                       touch "${DBDIR}/requires/$origin/status/COMPLETE.FAILED_FETCH.DISTCLEAN"
2605 #                               fi
2606                                 if [ ! -e "${DBDIR}/requires/$origin/status/COMPLETE.FAILED_FETCH.REFETCH" ]
2607                                 then
2608                                         env ${MAKE_ENVS} make fetch ${MAKE_ARGS} FETCH_ARGS=-Ap || \
2609                                         {
2610                                                 echo "ERROR: Failed in fetch for ${PORTSDIR}/$position_msg." >&2
2611                                                 echo 'fetch' > ${DBDIR}/requires/$origin/note_failtre
2612                                                 record_failure $origin
2613                                                 rm_a_line "$origin" "${DBDIR}/reinst_todo.list"
2614                                                 cmt_fail_reinst "$origin"
2615                                                 continue
2616                                         }
2617                                         env ${MAKE_ENVS} make checksum ${MAKE_ARGS} || \
2618                                         {
2619                                                 echo "ERROR: Failed in checksum for ${PORTSDIR}/$position_msg." >&2
2620                                                 echo 'checksum' > ${DBDIR}/requires/$origin/note_failtre
2621                                                 record_failure $origin
2622                                                 rm_a_line "$origin" "${DBDIR}/reinst_todo.list"
2623                                                 cmt_fail_reinst "$origin"
2624                                                 continue
2625                                         }
2626                                         touch "${DBDIR}/requires/$origin/status/COMPLETE.FAILED_FETCH.REFETCH"
2627                                 fi
2628                         fi
2629                         touch "${DBDIR}/requires/$origin/status/COMPLETE_FETCH"
2630                 fi
2631                 if [ ! -e "${DBDIR}/requires/$origin/status/COMPLETE_BUILD" ]
2632                 then
2633                         if env ${MAKE_ENVS} make ${MAKE_ARGS}
2634                         then
2635                                 :
2636                         elif [ $flag_restarted_build = yes ]
2637                         then
2638                                 rm "${DBDIR}/requires/$origin/status/COMPLETE_CLEAN_BEFORE_BUILD"
2639                                 echo "INFO: This failure may be due to restarting from a terminated build." >&2
2640                                 echo "WARNING: Retrying build after cleaning for ${PORTSDIR}/$position_msg." >&2
2641                                 env ${MAKE_ENVS} make clean ${MAKE_ARGS} || \
2642                                 {
2643                                         echo "ERROR: Check the permission of directory ${PORTSDIR}/$position_msg." >&2
2644                                         echo 'build and clean after build failure' > ${DBDIR}/requires/$origin/note_failtre
2645                                         record_failure $origin noclean
2646                                         rm_a_line "$origin" "${DBDIR}/reinst_todo.list"
2647                                         cmt_fail_reinst "$origin"
2648                                         continue
2649                                 }
2650                                 if env ${MAKE_ENVS} make ${MAKE_ARGS}
2651                                 then
2652                                         :
2653                                 else
2654                                         echo 'build' > ${DBDIR}/requires/$origin/note_failtre
2655                                         record_failure $origin
2656                                         rm_a_line "$origin" "${DBDIR}/reinst_todo.list"
2657                                         cmt_fail_reinst "$origin"
2658                                         continue
2659                                 fi
2660                         else
2661                                 echo 'build' > ${DBDIR}/requires/$origin/note_failtre
2662                                 record_failure $origin
2663                                 rm_a_line "$origin" "${DBDIR}/reinst_todo.list"
2664                                 cmt_fail_reinst "$origin"
2665                                 continue
2666                         fi
2667                         touch "${DBDIR}/requires/$origin/status/COMPLETE_BUILD"
2668                 fi
2669                 rm -f "${DBDIR}/requires/$origin/status/in_build"
2670                 if [ -e "${DBDIR}/requires/$origin/status/in_install" ]
2671                 then
2672                         echo "(Restarting the previously terminated installation process...)"
2673                 else
2674                         touch "${DBDIR}/requires/$origin/status/in_install"
2675                 fi
2676                 if [ -n "$currentpkg" -a ! -e "${DBDIR}/requires/$origin/status/COMPLETE_PKG_BACKUP" ]
2677                 then
2678                         echo "-- (Creating temporal backup package for $position_msg)"
2679                         backup_pkg=`create_backup_pkg "$currentpkg" "${DBDIR}/backup_failure"` || \
2680                         {
2681                                 rm -f "$backup_pkg"
2682                                 echo "WARNING: Failed to create the backup package, but ignored by hoping success." >&2
2683                         }
2684                         cd "${PORTSDIR}/$origin"
2685                         echo $currentpkg > ${DBDIR}/requires/$origin/backedup_version
2686                         echo $backup_pkg > ${DBDIR}/requires/$origin/backedup_pkgfile
2687                         touch "${DBDIR}/requires/$origin/status/COMPLETE_PKG_BACKUP"
2688                 fi
2689                 if [ -n "$currentpkg" -a ! -e "${DBDIR}/requires/$origin/status/COMPLETE_BEFOREDEINSTALL" ]
2690                 then
2691                         if [ -e "${DBDIR}/requires/$origin/BEFOREDEINSTALL.conflist" ]
2692                         then
2693                                 echo "-- BEFOREDEINSTALL operations (start)"
2694                                 sh -e "${DBDIR}/requires/$origin/BEFOREDEINSTALL.conflist" || \
2695                                 {
2696                                         echo "ERROR: while BEFOREDEINSTALL operations for ${PORTSDIR}/$position_msg." >&2
2697                                         echo 'BEFOREDEINSTALL operations' > ${DBDIR}/requires/$origin/note_failtre
2698                                         record_failure $origin noclean
2699                                         rm_a_line "$origin" "${DBDIR}/reinst_todo.list"
2700                                         cmt_fail_reinst "$origin"
2701                                         continue
2702                                 }
2703                                 echo "-- BEFOREDEINSTALL operations (end)"
2704                         fi
2705                         touch "${DBDIR}/requires/$origin/status/COMPLETE_BEFOREDEINSTALL"
2706                 fi
2707                 if [ -n "$currentpkg" -a ! -e "${DBDIR}/requires/$origin/status/COMPLETE_DEINSTALL" ]
2708                 then
2709                         pkg_delete_f $currentpkg || \
2710                         {
2711                                 echo "WARNING: Failed to deinstall $currentpkg by $command_pkg_delete." >&2
2712                         }
2713                         echo "-- (Trying to deinstall by ports to make sure. This usually ends up with warnings.)"
2714                         env ${MAKE_ENVS} make deinstall ${MAKE_ARGS} || \
2715                         {
2716                                 echo "WARNING: Failed to deinstall $currentpkg by make deinstall." >&2
2717                         }
2718                         touch "${DBDIR}/requires/$origin/status/COMPLETE_DEINSTALL"
2719                 fi
2720                 if [ ! -e "${DBDIR}/requires/$origin/status/COMPLETE_INSTALL" ]
2721                 then
2722                         if [ ! -e "${DBDIR}/requires/$origin/status/FAILED_INSTALL" ]
2723                         then
2724                                 if env ${MAKE_ENVS} make $insttarget ${MAKE_ARGS}
2725                                 then
2726                                         touch "${DBDIR}/requires/$origin/status/COMPLETE_INSTALL"
2727                                 else
2728                                         touch "${DBDIR}/requires/$origin/status/FAILED_INSTALL"
2729                                 fi
2730                         fi
2731                         if [ -e "${DBDIR}/requires/$origin/status/FAILED_INSTALL" ]
2732                         then
2733                                 if [ ! -e "${DBDIR}/requires/$origin/status/COMPETE.FAILED_INSTALL.RECOVER" ]
2734                                 then
2735                                         echo "*** Trying to deinstall the failed/terminated installation... (Ignore failures)"
2736                                         if [ -n "$currentpkg" ]
2737                                         then
2738                                                 pkg_delete_f $currentpkg || :
2739                                         fi
2740                                         echo "*** Trying to deinstall by ports to make sure. (This usually ends up with warnings)"
2741                                         env ${MAKE_ENVS} make deinstall ${MAKE_ARGS} || :
2742                                         backedup_version=`cat "${DBDIR}/requires/$origin/backedup_version" 2> /dev/null || :`
2743                                         if [ -n "$backedup_version" ]
2744                                         then
2745                                                 echo "*** Restoring the backup of $backedup_version..."
2746                                                 backup_pkg=`cat "${DBDIR}/requires/$origin/backedup_pkgfile" || :`
2747                                                 if [ -z "$backup_pkg" -o ! -e "$backup_pkg" ]
2748                                                 then
2749                                                         echo "WARNING: No backup exists, gave up." >&2
2750                                                 elif pkg_add_fF "$backup_pkg"
2751                                                 then
2752                                                         :
2753                                                 else
2754                                                         echo "WARNING: Failed to restore $backedup_version. Note that your system may experience troubles by this error." >&2
2755                                                 fi
2756                                         fi
2757                                         touch "${DBDIR}/requires/$origin/status/COMPETE.FAILED_INSTALL.RECOVER"
2758                                 fi
2759                                 if [ -n "$currentpkg" -a ! -e "${DBDIR}/requires/$origin/status/COMPETE.FAILED_INSTALL.AFTERINSTALL" -a -e "${DBDIR}/requires/$origin/AFTERINSTALL.conflist" ]
2760                                 then
2761                                         echo "-- AFTERINSTALL operations (start)"
2762                                         sh -e "${DBDIR}/requires/$origin/AFTERINSTALL.conflist" || { echo "-- (This error is ignored)"; }
2763                                         echo "-- AFTERINSTALL operations (end)"
2764                                         touch "${DBDIR}/requires/$origin/status/COMPETE.FAILED_INSTALL.AFTERINSTALL"
2765                                 fi
2766                                 echo 'install' > ${DBDIR}/requires/$origin/note_failtre
2767                                 record_failure $origin noclean
2768                                 rm_a_line "$origin" "${DBDIR}/reinst_todo.list"
2769                                 cmt_fail_reinst "$origin"
2770                                 continue
2771                         fi
2772                 fi
2773                 if [ -e "${DBDIR}/requires/$origin/AFTERINSTALL.conflist" -a ! -e "${DBDIR}/requires/$origin/status/in_install.AFTERINSTALL" ]
2774                 then
2775                         echo "-- AFTERINSTALL operations (start)"
2776                         sh -e "${DBDIR}/requires/$origin/AFTERINSTALL.conflist" || \
2777                         {
2778                                 echo "ERROR: while AFTERINSTALL operations for ${PORTSDIR}/$position_msg." >&2
2779                                 echo 'AFTERINSTALL operations' > ${DBDIR}/requires/$origin/note_failtre
2780                                 record_failure $origin noclean
2781                                 rm_a_line "$origin" "${DBDIR}/reinst_todo.list"
2782                                 cmt_fail_reinst "$origin"
2783                                 continue
2784                         }
2785                         echo "-- AFTERINSTALL operations (end)"
2786                         touch "${DBDIR}/requires/$origin/status/in_install.AFTERINSTALL"
2787                 fi
2788                 if [ ! -e "${DBDIR}/requires/$origin/status/COMPLETE_CLEAN_AFTER_INSTALL" ]
2789                 then
2790                         env ${MAKE_ENVS} make clean ${MAKE_ARGS} || \
2791                         {
2792                                 echo "WARNING: Failed to clean $position_msg." >&2
2793                         }
2794                         touch "${DBDIR}/requires/$origin/status/COMPLETE_CLEAN_AFTER_INSTALL"
2795                 fi
2796                 if [ ! -e "${DBDIR}/requires/$origin/status/COMPLETE_TELL_UPDATE_TO_DEPANDENTS" ]
2797                 then
2798                         if [ -e "${DBDIR}/requires/$origin/dependents" ]
2799                         then
2800                                 while read origin_dependent
2801                                 do
2802                                         touch "${DBDIR}/requires/$origin_dependent/need_reinstall_due_to_updated_requirements"
2803                                 done < ${DBDIR}/requires/$origin/dependents
2804                         fi
2805                         touch "${DBDIR}/requires/$origin/status/COMPLETE_TELL_UPDATE_TO_DEPANDENTS"
2806                 fi
2807                 rm -f "${DBDIR}/requires/$origin/need_reinstall_due_to_updated_requirements"
2808                 record_success $origin
2809                 [ -e "${DBDIR}/requires/$origin/failed_requirements" ] && cp "${DBDIR}/requires/$origin/failed_requirements" "${DBDIR}/requires/$origin/failed_requirements.previous"
2810                 rm_a_line "$origin" "${DBDIR}/reinst_todo.list"
2811                 backup_pkg=`cat "${DBDIR}/requires/$origin/backedup_pkgfile" || :`
2812                 [ -n "$backup_pkg" -a -e "$backup_pkg" ] && rm -f "$backup_pkg"
2813                 rm "${DBDIR}/requires/$origin/status/in_install"
2814                 _MSG_CURRENT_STAGE=${_MSG_CURRENT_STAGE_general}
2815                 echo
2816         done
2817         cd "$savedir"
2818         touch "${DBDIR}/COMPLETE_REINSTALLATION"
2819         _MSG_CURRENT_STAGE=
2820         echo
2821 fi
2822
2823 # Clean up obsolete or unused distfiles
2824 if [ ! -e "${DBDIR}/COMPLETE_CLEANUP_OBSLETE_DISTFILES" ]
2825 then
2826         echo "Starting to clean up obsolete or unused distfiles at `timestamp`"
2827         find "${DISTDIR}" -type f | grep -v -E -f "${DBDIR}/distfiles.grep.pattern" | while read distfile
2828         do
2829                 echo "  $distfile"
2830                 rm -f "$distfile"
2831         done
2832         touch "${DBDIR}/COMPLETE_CLEANUP_OBSLETE_DISTFILES"
2833         echo
2834 fi
2835
2836 # Rebuild of package database
2837 if [ ! -e "${DBDIR}/COMPLETE_REBUILD_PKGDB" ]
2838 then
2839         if which -s pkgdb
2840         then
2841                 echo "Starting to rebuild package database for portupgrade at `timestamp`"
2842                 pkgdb -fu
2843         fi
2844         touch "${DBDIR}/COMPLETE_REBUILD_PKGDB"
2845         echo
2846 fi
2847
2848 # Notice of failures
2849 touch "${DBDIR}/failed.list"
2850 if [ `cat "${DBDIR}/failed.list" | wc -l` -gt 0 ]
2851 then
2852         fold -s << eof
2853 *** (Re)installation of the following ports were unsuccessful.
2854  Please recover them manually.
2855  You are recommended to read ${PORTSDIR}/UPDATING to resolve the problems.
2856 If you have installed ports-mgmt/portupgrade or ports-mgmt/portupgrade-devel, pkg_updating(1) will be useful for this purpose.
2857  You can check whether the failed ports are already unnecessary by executing
2858         ${APPNAME} show dependents [failed_port_globs]
2859  For unnecessary failed ports, you can delete it by
2860         $command_pkg_delete -f [failed_port_globs]
2861 and then execute
2862         ${APPNAME} taboo add [deleted_port_globs]
2863  For necessary and manually successful ports, after resolving the problems,
2864 execute
2865         ${APPNAME} ok add [resolved_port_globs]
2866 and restart by
2867         ${APPNAME} redo
2868 ****************
2869         show_list_failure
2870 *** Warned by ${APPNAME}
2871
2872 eof
2873 fi
2874
2875 # End
2876 terminate_process ()
2877 {
2878 }
2879
2880 echo "All done at `timestamp`"