OSDN Git Service

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