OSDN Git Service

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