OSDN Git Service

7837a7135f6c62f232419d73289b09bc7a0bbb8a
[portsreinstall/current.git] / lib / libdatabase_query.sh
1 #!/bin/sh -e
2 # ==============================================================================
3 # portsreinstall library script
4 # - Operations for queries to the temporary database -
5 # Copyright (C) 2013-2022 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
6 # This software is distributed under the 2-Clause BSD License.
7 # ==============================================================================
8
9 # ============= Show a list of failed ports with their reasons =============
10 database_query_show_list_failure ()
11 {
12         local tmp_valid
13         tmp_valid=${TMPDIR}/database_query_show_list_failure:valid
14         if [ `cat "${DBDIR}/failed.list" 2> /dev/null | wc -l` -eq 0 ]
15         then
16                 message_echo "INFO: No item is registered in this list."
17                 return 1
18         fi
19         env LANG=C grep -v -E -f "${DBDIR}/ports_to_delete.grep_pattern" "${DBDIR}/failed.list" 2> /dev/null \
20                 | while read origin
21         do
22                 env LANG=C grep -q -Fx "$origin" "${DBDIR}/stage.loop_list/ports_to_delete" 2> /dev/null \
23                         || echo "$origin"
24         done > $tmp_valid
25         if [ `cat "$tmp_valid" 2> /dev/null | wc -l` -eq 0 ]
26         then
27                 message_echo "INFO: No valid item is registered in this list."
28                 return 1
29         fi
30         while read origin
31         do
32                 note=`cat "${DBDIR}/notes/$origin/note_failtre" 2> /dev/null || :`
33                 resolved=no
34                 env LANG=C grep -q -Fx "$origin" "${DBDIR}/manually_done.list" 2> /dev/null && resolved=yes
35                 pkgtag=`cat "${DBDIR}/moved_from/$origin/pkgtag" 2> /dev/null || :`
36                 if [ $opt_batch_mode = no ]
37                 then
38                         case $resolved in
39                         no )    resolved=;;
40                         yes )   resolved=', resolved';;
41                         esac
42                         if [ -n "$note" ]
43                         then
44                                 detail="while [$note]"
45                         else
46                                 detail="by unrecorded reasons"
47                         fi
48                         if [ -n "$pkgtag" ]
49                         then
50                                 echo "$origin ($pkgtag) (error $detail$resolved)"
51                         else
52                                 echo "$origin (error $detail$resolved)"
53                         fi
54                 else
55                         printf "%s\t%s\t%s\t%s\n" "$origin" "$pkgtag" "$note" "$resolved"
56                 fi
57         done < $tmp_valid
58         :
59 }
60
61 # ============= Show a list of failed restoration of conflict =============
62 database_query_show_list_failed_conflicts_restoration ()
63 {
64         if [ `cat "${DBDIR}/deleted_conflicts" 2> /dev/null | wc -l` -eq 0 ]
65         then
66                 message_echo "INFO: No item is registered in this list."
67                 return 1
68         fi
69         env LANG=C grep -v -E -f "${DBDIR}/ports_to_delete.grep_pattern_col1" "${DBDIR}/deleted_conflicts" \
70                 | while read origin pkg
71                 do
72                         pkg_regexp=`str_escape_regexp "$pkg"`
73                         against=`env LANG=C grep -E "^$pkg_regexp:" "${DBDIR}/forbidden_conflicts" 2> /dev/null | cut -d : -f 2,3 | sort -u`
74                         if [ $opt_batch_mode = no ]
75                         then
76                                 if [ -n "$pkg" ]
77                                 then
78                                         echo -n "$origin ($pkg)"
79                                 else
80                                         echo -n "$origin"
81                                 fi
82                                 if [ -n "$against" ]
83                                 then
84                                         echo -n " against "
85                                         against=`echo "$against" | sed 's/:/(/;s/$/)/' | tr '\n' ' '`
86                                         str_linearize_list_and "$against"
87                                 else
88                                         echo
89                                 fi
90                         else
91                                 against=`echo "$against" | tr '\n' '|' | sed 's/,$//'`
92                                 printf '%s\t%s\t%s\n' "$origin" "$pkg" "$against"
93                         fi
94                 done
95         :
96 }
97
98 # ============= Show installed ports which have been neither upgraded or reinstalled from the initial state =============
99 database_query_show_list_fossil ()
100 {
101         local srclist origin pkg
102         srclist=`ls "${DBDIR}"/fossil_pkgs/fossil_since_* | head -n 1`
103         [ -e "$srclist" ] || return 0
104         while read origin
105         do
106                 pkg=`pkgsys_get_init_pkg_from_orig "$origin"`
107                 pkg_info_e "$pkg" || continue
108                 printf '%s\t%s\n' "$origin" "$pkg"
109         done < $srclist
110 }
111
112 # ============= Insert initial flavored origins to a list of flavored origins =============
113 database_query_add_initial_origins ()
114 {
115         local origin
116         while read origin
117         do
118                 echo "$origin"
119                 [ -e "${DBDIR}/moved_from/$origin/initial_orig" ] || continue
120                 cat "${DBDIR}/moved_from/$origin/initial_orig"
121         done
122         :
123 }
124
125 # ============= Get target attributes =============
126 database_query_get_target_attributes ()
127 {
128         local prefix origin _is_all _is_target _is_requires_requirements _is_initial_requirements _is_requires_dependents _is_initial_dependents _is_requires_requirements_complement _is_relevant infofile tag level
129         prefix=$1
130         origin=$2
131         _is_all=y
132         _is_target=
133         _is_requires_requirements=
134         _is_initial_requirements=
135         _is_requires_dependents=
136         _is_initial_dependents=
137         _is_requires_requirements_complement=
138         _is_relevant=y
139         if [ ! -e "${DBDIR}/target_all" -a -n "$opt_target_itself$opt_target_dependents$opt_target_requirements" ]
140         then
141                 _is_all=
142                 tag=`options_get_dependency_type`
143                 level=full
144                 [ $opt_only_target_scope = yes ] && level=direct
145                 infofile=${DBDIR}/targets/$origin/attrs.${tag}.${level}
146                 if [ -e "$infofile" ]
147                 then
148                         . "$infofile"
149                 else
150                         _is_relevant=
151                 fi
152         fi
153         eval ${prefix}_is_all=\$\{_is_all\}
154         eval ${prefix}_is_target=\$\{_is_target\}
155         eval ${prefix}_is_requires_requirements=\$\{_is_requires_requirements\}
156         eval ${prefix}_is_initial_requirements=\$\{_is_initial_requirements\}
157         eval ${prefix}_is_requires_dependents=\$\{_is_requires_dependents\}
158         eval ${prefix}_is_initial_dependents=\$\{_is_initial_dependents\}
159         eval ${prefix}_is_requires_requirements_complement=\$\{_is_requires_requirements_complement\}
160         eval ${prefix}_is_relevant=\$\{_is_relevant\}
161 }
162
163 # ============= Check whether (re/de)installation of a port is suppressed =============
164 database_query_is_a_port_suppressed ()
165 {
166         local origin flags flag
167         origin=$1
168         flags=
169         [ $opt_suppress_self_upadte = yes ] && flags=SUPPRESSED_SELF
170         [ $opt_suppress_pkgtools_upadte = yes ] && flags="$flags SUPPRESSED_PKGNG"
171         for flag in $flags
172         do
173                 for db in initial moved_from
174                 do
175                         [ -e "${DBDIR}/$db/$origin/$flag" ] && return
176                 done
177         done
178         return 1
179 }
180
181 # ============= Check whether a port needs to be updated or upgraded =============
182 database_query_does_a_port_need_update ()
183 {
184         local origin dbpath frompath new_version current_version
185         origin=$1
186         dbpath=${DBDIR}/requires/$origin
187         frompath=${DBDIR}/moved_from/$origin
188         [ -e "$dbpath/conf_updated" ] && return
189         [ -e "$dbpath/new_version" ] || return
190         new_version=`cat "$dbpath/new_version"`
191         current_version=`cat "$frompath/current_version"`
192         [ "x$current_version" != "x$new_version" ]
193 }
194
195 # ============= Check before operations of a command which need the temporary database completely prepared =============
196 database_query_chk_preparation_completion ()
197 {
198         program_chk_stage_complete PREPARATION && return
199         message_echo "ERROR: Database has to be built completely before executing this command." >&2
200         exit 1
201 }
202
203 # ============= Get a make variable value of a port =============
204 database_query_get_makevar_val ()
205 {
206         local origin variable dbdir cache value
207         origin=$1
208         variable=$2
209         dbdir=${DBDIR}/requires/$origin
210         cache=$dbdir/makevar/$variable
211         if [ -e "$cache" ]
212         then
213                 cat "$cache"
214         else
215                 value=`database_build_make "$origin" -V "$variable"`
216                 if [ -d "$dbdir" ] && misc_is_superuser_privilege
217                 then
218                         [ -d "$dbdir/makevar" ] || mkdir "$dbdir/makevar"
219                         echo "$value" > $cache.tmp
220                         mv "$cache.tmp" "$cache"
221                 fi
222                 echo "$value"
223         fi
224 }
225
226 # ============= Get a configured value of a port =============
227 database_query_get_config_val ()
228 {
229         local origin variable dbdir cache value
230         origin=$1
231         variable=$2
232         dbfile=${DBDIR}/conf/each_port/$origin/$variable.conf
233         cat "$dbfile" 2> /dev/null || :
234 }
235
236 # ============= Check whether configurations for a port is default =============
237 database_query_is_default_conf ()
238 {
239         local origin mode dbpath tmp_msg is_customized is_requiremnt_replaced files tmp_old tmp_new origin_requirement tmp_msg_customized
240         origin=$1
241         mode=$2
242         dbpath=${DBDIR}/requires/$origin
243         if [ ! -e "$dbpath/is_customized" ]
244         then
245                 tmp_msg=${TMPDIR}/database_query_is_default_conf:msg
246                 cp /dev/null "$tmp_msg"
247                 is_customized=no
248                 if [ `ls "${DBDIR}/conf/each_port/$origin" 2> /dev/null | wc -l` -gt 0 ]
249                 then
250                         files=`ls "${DBDIR}/conf/each_port/$origin" | sed -E 's/^([^.]+).*/\1/' | str_concat_items_for_sentence`
251                         echo "Knobs and miscellaneous customization by $files," >> $tmp_msg
252                         is_customized=yes
253                 fi
254                 if ! diff -q "$dbpath/ports_options.default" "$dbpath/ports_options.current" > /dev/null 2>&1
255                 then
256                         echo "Non-default port options," >> $tmp_msg
257                         is_customized=yes
258                 fi
259                 if env LANG=C grep -q -Fx "$origin" "${DBDIR}/conf/NOPKG:PORTS.parsed" 2> /dev/null
260                 then
261                         echo "Explicit specification as non-default in ${APPNAME}.conf," >> $tmp_msg
262                         is_customized=yes
263                 fi
264                 tmp_old=${TMPDIR}/database_query_is_default_conf:old
265                 tmp_new=${TMPDIR}/database_query_is_default_conf:new
266                 is_requiremnt_replaced=no
267                 if fileedit_manipulate_old_new_lines "$dbpath/requirements.all.direct.orig" "$dbpath/requirements.all.direct" \
268                         "$tmp_old" "$tmp_new"
269                 then
270                         echo "Replacement in requirements:" >> $tmp_msg
271                         echo "-------- FROM --------" >> $tmp_msg
272                         sed 's/^/ /' "$tmp_old" >> $tmp_msg
273                         echo "--------  TO  --------" >> $tmp_msg
274                         sed 's/^/ /' "$tmp_new" >> $tmp_msg
275                         echo "----------------------" >> $tmp_msg
276                         is_customized=yes
277                 fi
278                 for origin_requirement in `cat "$dbpath/requirements.all.direct" 2> /dev/null`
279                 do
280                         database_query_is_default_conf "$origin_requirement" quiet && continue
281                         echo "Non-default requirement $origin_requirement," >> $tmp_msg
282                         is_customized=yes
283                 done
284                 { [ $is_customized = yes ] && cat "$tmp_msg"; } > $dbpath/is_customized.tmp
285                 mv "$dbpath/is_customized.tmp" "$dbpath/is_customized"
286         fi
287         [ `wc -c < $dbpath/is_customized` -eq 0 ] && return
288         if [ "x$mode" != xquiet ]
289         then
290                 tmp_msg_customized=${TMPDIR}/database_query_is_default_conf:msg_customized
291                 message_echo "INFO: This port is configured to be non-default because of"
292                 sed 's/^/         /' "$dbpath/is_customized" > $tmp_msg_customized
293                 message_cat "$tmp_msg_customized"
294                 message_echo "      so the prebuilt package is not used."
295         fi
296         return 1
297 }
298
299 # ============= Output of lists in which each matching port is registered =============
300 database_query_show_list_inclusion_of_matching_port ()
301 {
302         local grandtitle lists pkgnamedb deptag level isfirst origin_target pkg_target table_target
303         grandtitle=$1
304         lists=$2
305         pkgnamedb=$3
306         deptag=$4
307         level=$5
308         shift 5
309         message_echo "[$grandtitle]"
310         message_dependency_scope "$deptag" "$level"
311         message_echo
312         isfirst=y
313         for origin_target in `pkgsys_eval_ports_glob "$@"`
314         do
315                 pkg_target=
316                 for table_target in $pkgnamedb
317                 do
318                         pkg_target=`cat "${DBDIR}/$table_target/$origin_target/pkgtag" 2> /dev/null` || :
319                         [ -n "$pkg_target" ] && break
320                 done
321                 [ -n "$pkg_target" ] || continue
322                 isfirst=n
323                 match=
324                 for subject in `echo "$lists" | tr \| ' '`
325                 do
326                         database_query_exists_in_list "$origin_target" "$subject" "$deptag" "$level" \
327                                 && match="$match $subject"
328                 done
329                 if [ $opt_batch_mode = no ]
330                 then
331                         echo -n "$origin_target ($pkg_target): "
332                         echo "$match" | sed 's/^ *//;s/ /, /g'
333                 else
334                         printf '%s\t%s\t' "$origin_target" "$pkg_target"
335                         echo "$match" | sed 's/^ *//;s/ /,/g'
336                 fi
337         done
338         if [ "$isfirst" = y ]
339         then
340                 message_echo "ERROR: No inspected port matches the glob(s)." >&2
341                 exit 1
342         fi
343         :
344 }
345
346 # ============= Output of "show" command for port lists =============
347 database_query_show_port_lists ()
348 {
349         local grandtitle title list listdb pkgnamedb deptag level isfirst origin_target pkg_target table_target list_target
350         grandtitle=$1
351         title=$2
352         list=$3
353         listdb=$4
354         pkgnamedb=$5
355         deptag=$6
356         level=$7
357         shift 7
358         message_echo "[$grandtitle]"
359         message_dependency_scope "$deptag" "$level"
360         message_echo
361         isfirst=y
362         for origin_target in `pkgsys_eval_ports_glob "$@"`
363         do
364                 pkg_target=
365                 for table_target in $pkgnamedb
366                 do
367                         pkg_target=`cat "${DBDIR}/$table_target/$origin_target/pkgtag" 2> /dev/null` || :
368                         [ -n "$pkg_target" ] && break
369                 done
370                 [ -n "$pkg_target" ] || continue
371                 [ "$isfirst" = y ] || message_echo
372                 isfirst=n
373                 [ $opt_batch_mode = no ] && printf "$title\n" "$origin_target ($pkg_target)"
374                 list_target=
375                 for table_target in $listdb
376                 do
377                         list_target=${DBDIR}/$table_target/$origin_target/$list
378                         [ -e "$list_target" ] && break
379                 done
380                 [ -e "$list_target" ] || continue
381                 if [ $opt_batch_mode = no ]
382                 then
383                         while read origin
384                         do
385                                 pkg=
386                                 for table in $pkgnamedb
387                                 do
388                                         pkg=`cat "${DBDIR}/$table/$origin/pkgtag" 2> /dev/null` || :
389                                         [ -n "$pkg" ] && break
390                                 done
391                                 [ -n "$pkg" ] || continue
392                                 echo "$origin ($pkg)"
393                         done < $list_target
394                 else
395                         while read origin
396                         do
397                                 pkg=
398                                 for table in $pkgnamedb
399                                 do
400                                         pkg=`cat "${DBDIR}/$table/$origin/pkgtag" 2> /dev/null` || :
401                                         [ -n "$pkg" ] && break
402                                 done
403                                 [ -n "$pkg" ] || continue
404                                 printf '%s\t%s\t%s\t%s\n' "$origin_target" "$pkg_target" "$origin" "$pkg"
405                         done < $list_target
406                 fi
407         done
408         if [ "$isfirst" = y ]
409         then
410                 message_echo "ERROR: No inspected port matches the glob(s)." >&2
411                 exit 1
412         fi
413         :
414 }
415
416 # ============= Output of "show" command for log files =============
417 database_query_show_log ()
418 {
419         local grandtitle title list listdb pkgnamedb isfirst origin_target pkg_target table_target list_target
420         grandtitle=$1
421         title=$2
422         list=$3
423         listdb=$4
424         pkgnamedb=$5
425         shift 5
426         message_echo "[$grandtitle]"
427         message_echo
428         isfirst=y
429         for origin_target in `pkgsys_eval_ports_glob "$@"`
430         do
431                 pkg_target=
432                 for table_target in $pkgnamedb
433                 do
434                         pkg_target=`cat "${DBDIR}/$table_target/$origin_target/pkgtag" 2> /dev/null` || :
435                         [ -n "$pkg_target" ] && break
436                 done
437                 [ -n "$pkg_target" ] || continue
438                 [ "$isfirst" = y ] || message_echo
439                 isfirst=n
440                 [ $opt_batch_mode = no ] && printf "$title\n" "$origin_target ($pkg_target)"
441                 list_target=
442                 for table_target in $listdb
443                 do
444                         list_target=${DBDIR}/$table_target/$origin_target/$list
445                         [ -e "$list_target" ] && break
446                 done
447                 [ -e "$list_target" ] || continue
448                 cat  < $list_target
449                 echo
450         done
451         if [ "$isfirst" = y ]
452         then
453                 message_echo "ERROR: No inspected port matches the glob(s)." >&2
454                 exit 1
455         fi
456         :
457 }
458
459 # ============= Output of "show" command for two column lists =============
460 database_query_show_two_column_lists ()
461 {
462         local grandtitle title list listdb pkgnamedb isfirst origin_target pkg_target table_target list_target
463         grandtitle=$1
464         title=$2
465         list=$3
466         listdb=$4
467         pkgnamedb=$5
468         shift 5
469         message_echo "[$grandtitle]"
470         message_echo
471         isfirst=y
472         for origin_target in `pkgsys_eval_ports_glob "$@"`
473         do
474                 pkg_target=
475                 for table_target in $pkgnamedb
476                 do
477                         pkg_target=`cat "${DBDIR}/$table_target/$origin_target/pkgtag" 2> /dev/null` || :
478                         [ -n "$pkg_target" ] && break
479                 done
480                 [ -n "$pkg_target" ] || continue
481                 [ "$isfirst" = y ] || message_echo
482                 isfirst=n
483                 [ $opt_batch_mode = no ] && printf "$title\n" "$origin_target ($pkg_target)"
484                 list_target=
485                 for table_target in $listdb
486                 do
487                         list_target=${DBDIR}/$table_target/$origin_target/$list
488                         [ -e "$list_target" ] && break
489                 done
490                 [ -e "$list_target" ] || continue
491                 if [ $opt_batch_mode = no ]
492                 then
493                         sed 's/[[:space:]]/: /' < $list_target
494                 else
495                         cat  < $list_target
496                 fi
497         done
498         if [ "$isfirst" = y ]
499         then
500                 message_echo "ERROR: No inspected port matches the glob(s)." >&2
501                 exit 1
502         fi
503         :
504 }
505
506 # ============= Output of "show" command for a single list =============
507 database_query_show_single_list ()
508 {
509         local list pkgnamedb flag_filter_skip_unchanged flag_filter_only_target flag_negative_listdb tmpflag_exists put_blankline origin matches_negative matches_positive flag pkg table
510         local currentorigin_is_alll currentorigin_is_target currentorigin_is_requires_requirements
511         local currentorigin_is_initial_requirements currentorigin_is_requires_dependents
512         local currentorigin_is_initial_dependents currentorigin_is_requires_requirements_complement currentorigin_is_relevant
513         list=$1
514         pkgnamedb=$2
515         flag_filter_skip_unchanged=$3
516         flag_filter_only_target=$4
517         flag_negative_listdb=$5
518         tmpflag_exists=${TMPDIR}/database_query_show_single_list::exists_item
519         if [ `cat "${DBDIR}/$list" 2> /dev/null | wc -l` -eq 0 ]
520         then
521                 message_echo "INFO: No item is registered in this list."
522                 return 1
523         fi
524         if ! program_chk_stage_complete PREPARATION
525         then
526                 message_echo "WARNING: The temporary database is incomplete. The raw list is shown." >&2
527                 cat "${DBDIR}/$list"
528                 return
529         fi
530         rm -f "$tmpflag_exists"
531         put_blankline=
532         if [ -n "$flag_filter_only_target" \
533                 -a -n "$opt_target_itself$opt_target_dependents$opt_target_requirements" ]
534         then
535                 message_echo "WARNING: Ports outside of the target scope are excluded." >&2
536                 put_blankline=y
537         fi
538         if [ -n "$flag_filter_skip_unchanged" -a $opt_skip_unchanged = yes ]
539         then
540                 message_echo "WARNING: Ports which have been the newest with their all requirements from the first are excluded." >&2
541                 put_blankline=y
542         fi
543         [ -n "$put_blankline" ] && message_echo
544         while read origin
545         do
546                 matches_negative=no
547                 for negative_listdb in $flag_negative_listdb
548                 do
549                         if env LANG=C grep -qFx "$origin" "${DBDIR}/$negative_listdb" 2> /dev/null
550                         then
551                                 matches_negative=yes
552                                 break
553                         fi
554                 done
555                 [ $matches_negative = yes ] && continue
556                 if [ -n "$flag_filter_skip_unchanged" -a $opt_skip_unchanged = yes ]
557                 then
558                         matches_positive=no
559                         for flag in $flag_filter_skip_unchanged
560                         do
561                                 if [ -e "${DBDIR}/requires/$origin/$flag" ]
562                                 then
563                                         matches_positive=yes
564                                         break
565                                 fi
566                         done
567                         [ $matches_positive = no ] && continue
568                 fi
569                 if [ -n "$flag_filter_only_target" ]
570                 then
571                         database_query_get_target_attributes currentorigin "$origin"
572                         [ -n "${currentorigin_is_relevant}" ] || continue
573                         database_query_is_a_port_suppressed "$origin" && continue
574                 fi
575                 pkg=
576                 for table in $pkgnamedb
577                 do
578                         pkg=`cat "${DBDIR}/$table/$origin/pkgtag" 2> /dev/null` || :
579                         [ -n "$pkg" ] && break
580                 done
581                 [ -n "$pkg" ] || continue
582                 touch "$tmpflag_exists"
583                 if [ $opt_batch_mode = no ]
584                 then
585                         echo "$origin ($pkg)"
586                 else
587                         printf '%s\t%s\n' "$origin" "$pkg"
588                 fi
589         done < ${DBDIR}/$list
590         [ -e "$tmpflag_exists" ] && return
591         message_echo "INFO: No item is registered in this list."
592         return 1
593 }
594
595 # ============= Check whether the upgrade is necessary for a port =============
596 database_query_is_necessary_upgrade ()
597 {
598         local origin nodedir dbsuffix tmpfile_new tmpfile_old tmpfile_diff
599         origin=$1
600         nodedir=${DBDIR}/requires/$origin
601         [ -e "$nodedir/installed_by_pkg" ] && return 1
602         dbsuffix=`options_get_dependency_type`.`options_get_dependency_level`
603         tmpfile_new=${TMPDIR}/database_query_is_necessary_upgrade:failed_requirements.new
604         tmpfile_old=${TMPDIR}/database_query_is_necessary_upgrade:failed_requirements.old
605         tmpfile_diff=${TMPDIR}/database_query_is_necessary_upgrade:failed_requirements.diff
606         [ -e "$nodedir/failed_requirements.${dbsuffix}.previous" ] || return
607         sort -u "$nodedir/failed_requirements.${dbsuffix}" > $tmpfile_new 2> /dev/null || :
608         sort -u "$nodedir/failed_requirements.${dbsuffix}.previous" > $tmpfile_old 2> /dev/null || :
609         fileedit_exists_old_lines "$tmpfile_old" "$tmpfile_new"
610 }
611
612 # ============= Show moved or replaced ports to alternatives =============
613 database_query_show_list_moved ()
614 {
615         cat "${DBDIR}/moved_ports" 2> /dev/null | while read origin
616         do
617                 lastorigin=$origin
618                 while [ -n "$lastorigin" -a -e "${DBDIR}/replace/$lastorigin/origin" ]
619                 do
620                         lastorigin=`cat "${DBDIR}/replace/$lastorigin/origin"`
621                 done
622                 [ -n "$lastorigin" ] || continue
623                 pkg=
624                 for table in $pkgnamedb
625                 do
626                         pkg=`cat "${DBDIR}/$table/$origin/pkgtag" 2> /dev/null` || :
627                         [ -n "$pkg" ] && break
628                 done
629                 [ -n "$pkg" ] || pkg='not installed'
630                 lastpkg=
631                 for table in moved_from obsolete initial
632                 do
633                         lastpkg=`cat "${DBDIR}/$table/$lastorigin/pkgtag" 2> /dev/null` || :
634                         [ -n "$lastpkg" ] && break
635                 done
636                 [ -n "$lastpkg" ] || lastpkg='not installed'
637                 if [ $opt_batch_mode = no ]
638                 then
639                         echo "$origin ($pkg) => $lastorigin ($lastpkg)"
640                 else
641                         printf '%s\t%s\t%s\t%s\n' "$origin" "$pkg" "$lastorigin" "$lastpkg"
642                 fi
643         done
644 }
645
646 # ============= Actual operations of "show" command for a single list =============
647 database_query_show_single_list_exec ()
648 {
649         local subject deptag level dbsuffix flag_filter_skip_unchanged flag_filter_only_target flag_negative_listdb pkgnamedb
650         subject=$1
651         deptag=$2
652         level=$3
653         dbsuffix=$deptag.$level
654         flag_filter_skip_unchanged=
655         flag_filter_only_target=
656         flag_negative_listdb=
657         pkgnamedb='moved_from obsolete initial'
658         case $subject in
659         todo )
660                 message_echo "The following ports remain in the (re)installation queue for the current do/redo process:"
661                 message_echo "It is noted that ports to be skipped can be included here."
662                 message_dependency_scope "$deptag" "$level"
663                 message_echo
664                 list=stage.loop_list/reinst_todo.remain
665                 [ ${DBDIR}/reinst_order.list -nt ${DBDIR}/$list ] && list=reinst_order.list
666                 flag_filter_skip_unchanged=necessary_upgrade.$dbsuffix
667                 flag_filter_only_target=y
668                 ;;
669         done )
670                 message_echo "The following ports have been successfully (re)installed or newly installed:"
671                 message_dependency_scope "$deptag" "$level"
672                 message_echo
673                 list=success.$dbsuffix.list
674                 flag_filter_skip_unchanged=necessary_upgrade_completed.$dbsuffix
675                 flag_filter_only_target=y
676                 ;;
677         redo )
678                 message_echo "The following ports need (re)installation after success of the all requirements:"
679                 message_dependency_scope "$deptag" "$level"
680                 message_echo
681                 list=todo_after_requirements_succeed.$dbsuffix.list
682                 flag_filter_skip_unchanged="necessary_upgrade.$dbsuffix necessary_upgrade_completed.$dbsuffix"
683                 flag_filter_only_target=y
684                 flag_negative_listdb=leaf_ports_to_delete.selected
685                 ;;
686         resolved )
687                 message_echo "The following ports had problems which have been manually resolved:"
688                 message_echo
689                 list=manually_done.list
690                 ;;
691         inst_by_pkg )
692                 message_echo "The following ports are configured default and installed by prebuilt packages"
693                 message_echo
694                 list=installation_complete_by_pkg.list
695                 ;;
696         inst_built_default )
697                 message_echo "The following ports are configured default and installed by ports"
698                 message_echo
699                 list=inst_by_port_with_default_conf.list
700                 ;;
701         inst_built_custom )
702                 message_echo "The following ports are configured non-default and installed by ports"
703                 message_echo
704                 list=inst_by_port_with_custom_conf.list
705                 ;;
706         failure )
707                 message_echo "The following ports experienced failures and kept to be old or uninstalled:"
708                 message_echo
709                 database_query_show_list_failure
710                 return
711                 ;;
712         fossil )
713                 message_echo "The following ports are neither upgraded or reinstalled from the initial state:"
714                 message_echo
715                 database_query_show_list_fossil
716                 return
717                 ;;
718         conflict )
719                 message_echo "The following ports are temporarily deleted due to conflict:"
720                 message_echo
721                 database_query_show_list_failed_conflicts_restoration
722                 return
723                 ;;
724         moved )
725                 message_echo "The following ports are moved/replaced to new alternatives:"
726                 message_echo
727                 database_query_show_list_moved
728                 return
729                 ;;
730         taboo )
731                 message_echo "The following ports are registered as taboo:"
732                 message_echo
733                 list=taboo.all.list
734                 ;;
735         freeze )
736                 message_echo "The following ports are registered to freeze:"
737                 message_echo
738                 list=freeze.all.list
739                 ;;
740         need )
741                 message_echo "The following ports are registered as necessary:"
742                 message_echo
743                 list=need.list
744                 ;;
745         noneed )
746                 message_echo "The following ports are registered as unnecessary:"
747                 message_echo
748                 list=noneed.list
749                 ;;
750         restored )
751                 message_echo "The following leaf, obsolete or unneeded ports had been once deleted but are to be or have been restored:"
752                 message_echo
753                 list=stage.loop_list/ports_to_restore
754                 pkgnamedb='moved_from obsolete initial'
755                 flag_filter_only_target=y
756                 ;;
757         deleted )
758                 message_echo "The following leaf, obsolete or unneeded ports are to be or have been deleted:"
759                 message_echo
760                 list=stage.loop_list/ports_to_delete
761                 pkgnamedb='moved_from obsolete initial'
762                 flag_filter_only_target=y
763                 ;;
764         leaves )
765                 if [ -z "$deptag" ]
766                 then
767                         message_echo "The following ports are all detected leaf ports:"
768                         list=leaf_ports
769                 else
770                         message_echo "The following ports are all $deptag leaf ports:"
771                         list=leaf_ports_to_delete.$deptag
772                 fi
773                 message_echo
774                 pkgnamedb='moved_from obsolete initial'
775                 flag_filter_only_target=y
776                 ;;
777         obsolete )
778                 if [ -z "$deptag" ]
779                 then
780                         message_echo "The following ports are all detected obsolete ports:"
781                         list=obsolete_ports.can_be_deleted
782                 else
783                         message_echo "The following ports are all $deptag obsolete ports:"
784                         list=obsolete_ports_to_delete.$deptag
785                 fi
786                 message_echo
787                 pkgnamedb='moved_from obsolete initial'
788                 flag_filter_only_target=y
789                 ;;
790         esac
791         database_query_show_single_list "$list" "$pkgnamedb" \
792                 "$flag_filter_skip_unchanged" "$flag_filter_only_target" "$flag_negative_listdb"
793 }
794
795 # ============= Check whether a port is registered in a list =============
796 database_query_exists_in_list ()
797 {
798         local origin subject deptag level tmp_list dbsuffix origin_esc
799         origin=$1
800         subject=$2
801         deptag=$3
802         level=$4
803         tmp_list=${TMPDIR}/database_query_exists_in_list:list
804         dbsuffix=$deptag.$level
805         origin_esc=`str_escape_regexp "$origin"`
806         case $subject in
807         todo )
808                 list=stage.loop_list/reinst_todo.remain
809                 [ ${DBDIR}/reinst_order.list -nt ${DBDIR}/$list ] && list=reinst_order.list
810                 ;;
811         done )
812                 list=success.$dbsuffix.list
813                 ;;
814         redo )
815                 list=todo_after_requirements_succeed.$dbsuffix.list
816                 ;;
817         resolved )
818                 list=manually_done.list
819                 ;;
820         inst_by_pkg )
821                 list=installation_complete_by_pkg.list
822                 ;;
823         inst_built_default )
824                 list=inst_by_port_with_default_conf.list
825                 ;;
826         inst_built_custom )
827                 list=inst_by_port_with_custom_conf.list
828                 ;;
829         failure )
830                 list=failed.list
831                 ;;
832         fossil )
833                 list=`ls "${DBDIR}"/fossil_pkgs/fossil_since_* | head -n 1`
834                 ;;
835         conflict )
836                 env LANG=C grep -v -E -f "${DBDIR}/ports_to_delete.grep_pattern_col1" "${DBDIR}/deleted_conflicts" 2> /dev/null \
837                         | env LANG=C grep -q -E "^${origin_esc}[[:space:]]"
838                 return
839                 ;;
840         taboo )
841                 list=taboo.all.list
842                 ;;
843         freeze )
844                 list=freeze.all.list
845                 ;;
846         need )
847                 list=need.list
848                 ;;
849         noneed )
850                 list=noneed.list
851                 ;;
852         restored )
853                 list=stage.loop_list/ports_to_restore
854                 ;;
855         deleted )
856                 list=stage.loop_list/ports_to_delete
857                 ;;
858         esac
859         env LANG=C grep -q -Fx "$origin" "${DBDIR}/$list" 2> /dev/null
860 }
861
862 # ============= Check whether the requirements of installed packages match the port configuration =============
863 database_query_dependency_matching ()
864 {
865         local origin pkg tmp_inst tmp_db
866         origin=$1
867         [ -d "${DBDIR}/requires/$origin" ] || return
868         tmp_inst=${TMPDIR}/database_query_dependency_matching.installed
869         tmp_db=${TMPDIR}/database_query_dependency_matching.configured
870         pkg=`database_build_get_new_pkgname "$origin"`
871         [ -n "$pkg" ] || return
872         pkg_info_e "$pkg" || return
873         pkg_info_qr "$pkg" | env LANG=C grep -v '^[[:space:]]*$' | sort -u > $tmp_inst
874         database_build_get_full_run_requirement_pkgs "$origin" > $tmp_db
875         diff "$tmp_inst" "$tmp_db" > /dev/null 2>/dev/null
876 }
877
878 # ============= Check whether any of the requirements are locked because being missing ports to freeze =============
879 database_query_are_requirements_not_locked ()
880 {
881         local origin
882         origin=$1
883         cat "${DBDIR}/requires/$origin/requirements.all.direct" 2> /dev/null | while read origin_requirement
884         do
885                 pkg_requirement=`pkgsys_get_installed_pkg_from_origin "$origin_requirement"` || :
886                 if env LANG=C grep -q -Fx "$origin_requirement" "${DBDIR}/freeze.all.list" 2> /dev/null
887                 then
888                         [ -n "$pkg_requirement" ] || return
889                 elif [ -z "$pkg_requirement" ]
890                 then
891                         database_query_are_requirements_not_locked "$origin_requirement" || return
892                 fi
893         done
894         :
895 }
896
897 # ============= Check whether any of progress is made in the current run =============
898 database_query_is_any_progress ()
899 {
900         [ `cat "${DBDIR}/new_success_in_current_run" 2> /dev/null | wc -l` -gt 0 ]
901 }
902
903 # ============= Get the all initial origins, separated by line feed =============
904 database_query_initial_orgins ()
905 {
906         local origin origin_init
907         origin=$1
908         if [ -e "${DBDIR}/moved_from/$origin/old_origs" ]
909         then
910                 for origin_init in `cat "${DBDIR}/moved_from/$origin/old_origs"`
911                 do
912                         [ -e "${DBDIR}/initial/$origin_init/installed_version" ] && echo "$origin_init"
913                 done
914         else
915                 [ -e "${DBDIR}/initial/$origin/installed_version" ] && echo "$origin"
916         fi
917         :
918 }
919
920 # ============= Get an unflavored or flavored equivalence of an origin with the same package name, which is deemed the same version =============
921 # If the input is unflavored and a flavored equivalence is inspected as a required port, the flavored origin is returned.
922 # If the input is flavored and an unflavored equivalence is inspected as a required port, the unflavored origin is returned.
923 # Otherwise, a blank value is returned.
924 database_query_get_equivalent_orgin ()
925 {
926         local origin origin_esc pkg_origin pkg_origin_esc flavor origin_unflavored_esc origin_search
927         origin=$1
928         origin_esc=`str_escape_regexp "$origin"`
929         pkg_origin=`env LANG=C grep -E "[[:space:]]$origin_esc$" "${DBDIR}/installed_ports:pkg_vs_origin.tbl" | cut -f 2 || :`
930         [ -n "$pkg_origin" ] || return 0
931         pkg_origin_esc=`str_escape_regexp "$pkg_origin"`
932         flavor=`pkgsys_get_flavor_from_origin "$origin"`
933         origin_search=$origin_unflavored_esc$
934         [ -n "$flavor" ] || origin_search=$origin_esc@
935         env LANG=C grep -E "^$pkg_origin_esc[[:space:]]$origin_search" "${DBDIR}/installed_ports:pkg_vs_origin.tbl" | cut -f 2 | head -n 1 || :
936 }