OSDN Git Service

807ee2a617b19b84075dc36227e506138799fbd3
[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-2018 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         grep -v -E -f "${DBDIR}/ports_to_delete.grep_pattern" "${DBDIR}/failed.list" 2> /dev/null \
20                 | while read origin
21         do
22                 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                 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         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=`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 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 tmpflag_exists put_blankline
510         list=$1
511         pkgnamedb=$2
512         flag_filter_skip_unchanged=$3
513         flag_filter_only_target=$4
514         tmpflag_exists=${TMPDIR}/database_query_show_single_list::exists_item
515         if [ `cat "${DBDIR}/$list" 2> /dev/null | wc -l` -eq 0 ]
516         then
517                 message_echo "INFO: No item is registered in this list."
518                 return 1
519         fi
520         if ! program_chk_stage_complete PREPARATION
521         then
522                 message_echo "WARNING: The temporary database is incomplete. The raw list is shown." >&2
523                 cat "${DBDIR}/$list"
524                 return
525         fi
526         rm -f "$tmpflag_exists"
527         put_blankline=
528         if [ -n "$flag_filter_only_target" \
529                 -a -n "$opt_target_itself$opt_target_dependents$opt_target_requirements" ]
530         then
531                 message_echo "WARNING: Ports outside of the target scope are excluded." >&2
532                 put_blankline=y
533         fi
534         if [ -n "$flag_filter_skip_unchanged" -a $opt_skip_unchanged = yes ]
535         then
536                 message_echo "WARNING: Ports which have been the newest with their all requirements from the first are excluded." >&2
537                 put_blankline=y
538         fi
539         [ -n "$put_blankline" ] && message_echo
540         while read origin
541         do
542                 [ -n "$flag_filter_skip_unchanged" -a $opt_skip_unchanged = yes \
543                         -a ! -e "${DBDIR}/requires/$origin/$flag_filter_skip_unchanged" ] \
544                         && continue
545                 if [ -n "$flag_filter_only_target" ]
546                 then
547                         database_query_get_target_attributes currentorigin "$origin"
548                         [ -n "${currentorigin_is_relevant}" ] || continue
549                         database_query_is_a_port_suppressed "$origin" && continue
550                 fi
551                 pkg=
552                 for table in $pkgnamedb
553                 do
554                         pkg=`cat "${DBDIR}/$table/$origin/pkgtag" 2> /dev/null` || :
555                         [ -n "$pkg" ] && break
556                 done
557                 [ -n "$pkg" ] || continue
558                 touch "$tmpflag_exists"
559                 if [ $opt_batch_mode = no ]
560                 then
561                         echo "$origin ($pkg)"
562                 else
563                         printf '%s\t%s\n' "$origin" "$pkg"
564                 fi
565         done < ${DBDIR}/$list
566         [ -e "$tmpflag_exists" ] && return
567         message_echo "INFO: No item is registered in this list."
568         return 1
569 }
570
571 # ============= Check whether the upgrade is necessary for a port =============
572 database_query_is_necessary_upgrade ()
573 {
574         local origin nodedir dbsuffix tmpfile_new tmpfile_old tmpfile_diff
575         origin=$1
576         nodedir=${DBDIR}/requires/$origin
577         [ -e "$nodedir/installed_by_pkg" ] && return 1
578         dbsuffix=`options_get_dependency_type`.`options_get_dependency_level`
579         tmpfile_new=${TMPDIR}/database_query_is_necessary_upgrade:failed_requirements.new
580         tmpfile_old=${TMPDIR}/database_query_is_necessary_upgrade:failed_requirements.old
581         tmpfile_diff=${TMPDIR}/database_query_is_necessary_upgrade:failed_requirements.diff
582         [ -e "$nodedir/failed_requirements.${dbsuffix}.previous" ] || return
583         sort -u "$nodedir/failed_requirements.${dbsuffix}" > $tmpfile_new 2> /dev/null || :
584         sort -u "$nodedir/failed_requirements.${dbsuffix}.previous" > $tmpfile_old 2> /dev/null || :
585         fileedit_exists_old_lines "$tmpfile_old" "$tmpfile_new"
586 }
587
588 # ============= Show moved or replaced ports to alternatives =============
589 database_query_show_list_moved ()
590 {
591         cat "${DBDIR}/moved_ports" 2> /dev/null | while read origin
592         do
593                 lastorigin=$origin
594                 while [ -n "$lastorigin" -a -e "${DBDIR}/replace/$lastorigin/origin" ]
595                 do
596                         lastorigin=`cat "${DBDIR}/replace/$lastorigin/origin"`
597                 done
598                 [ -n "$lastorigin" ] || continue
599                 pkg=
600                 for table in $pkgnamedb
601                 do
602                         pkg=`cat "${DBDIR}/$table/$origin/pkgtag" 2> /dev/null` || :
603                         [ -n "$pkg" ] && break
604                 done
605                 [ -n "$pkg" ] || pkg='not installed'
606                 lastpkg=
607                 for table in moved_from obsolete initial
608                 do
609                         lastpkg=`cat "${DBDIR}/$table/$lastorigin/pkgtag" 2> /dev/null` || :
610                         [ -n "$lastpkg" ] && break
611                 done
612                 [ -n "$lastpkg" ] || lastpkg='not installed'
613                 if [ $opt_batch_mode = no ]
614                 then
615                         echo "$origin ($pkg) => $lastorigin ($lastpkg)"
616                 else
617                         printf '%s\t%s\t%s\t%s\n' "$origin" "$pkg" "$lastorigin" "$lastpkg"
618                 fi
619         done
620 }
621
622 # ============= Actual operations of "show" command for a single list =============
623 database_query_show_single_list_exec ()
624 {
625         local subject deptag level dbsuffix flag_filter_skip_unchanged flag_filter_only_target pkgnamedb
626         subject=$1
627         deptag=$2
628         level=$3
629         dbsuffix=$deptag.$level
630         flag_filter_skip_unchanged=
631         flag_filter_only_target=
632         pkgnamedb='moved_from obsolete initial'
633         case $subject in
634         todo )
635                 message_echo "The following ports remain in the (re)installation queue for the current do/redo process:"
636                 message_echo "It is noted that ports to be skipped can be included here."
637                 message_dependency_scope "$deptag" "$level"
638                 message_echo
639                 list=stage.loop_list/reinst_todo.remain
640                 [ ${DBDIR}/reinst_order.list -nt ${DBDIR}/$list ] && list=reinst_order.list
641                 flag_filter_skip_unchanged=necessary_upgrade.$dbsuffix
642                 flag_filter_only_target=y
643                 ;;
644         done )
645                 message_echo "The following ports have been successfully (re)installed or newly installed:"
646                 message_dependency_scope "$deptag" "$level"
647                 message_echo
648                 list=success.$dbsuffix.list
649                 flag_filter_skip_unchanged=necessary_upgrade_completed.$dbsuffix
650                 flag_filter_only_target=y
651                 ;;
652         redo )
653                 message_echo "The following ports need (re)installation after success of the all requirements:"
654                 message_dependency_scope "$deptag" "$level"
655                 message_echo
656                 list=todo_after_requirements_succeed.$dbsuffix.list
657                 flag_filter_skip_unchanged=necessary_upgrade.$dbsuffix
658                 flag_filter_only_target=y
659                 ;;
660         resolved )
661                 message_echo "The following ports had problems which have been manually resolved:"
662                 message_echo
663                 list=manually_done.list
664                 ;;
665         inst_by_pkg )
666                 message_echo "The following ports are configured default and installed by prebuilt packages"
667                 message_echo
668                 list=installation_complete_by_pkg.list
669                 ;;
670         inst_built_default )
671                 message_echo "The following ports are configured default and installed by ports"
672                 message_echo
673                 list=inst_by_port_with_default_conf.list
674                 ;;
675         inst_built_custom )
676                 message_echo "The following ports are configured non-default and installed by ports"
677                 message_echo
678                 list=inst_by_port_with_custom_conf.list
679                 ;;
680         failure )
681                 message_echo "The following ports experienced failures and kept to be old or uninstalled:"
682                 message_echo
683                 database_query_show_list_failure
684                 return
685                 ;;
686         fossil )
687                 message_echo "The following ports are neither upgraded or reinstalled from the initial state:"
688                 message_echo
689                 database_query_show_list_fossil
690                 return
691                 ;;
692         conflict )
693                 message_echo "The following ports are temporarily deleted due to conflict:"
694                 message_echo
695                 database_query_show_list_failed_conflicts_restoration
696                 return
697                 ;;
698         moved )
699                 message_echo "The following ports are moved/replaced to new alternatives:"
700                 message_echo
701                 database_query_show_list_moved
702                 return
703                 ;;
704         taboo )
705                 message_echo "The following ports are registered as taboo:"
706                 message_echo
707                 list=taboo.all.list
708                 ;;
709         freeze )
710                 message_echo "The following ports are registered to freeze:"
711                 message_echo
712                 list=freeze.all.list
713                 ;;
714         need )
715                 message_echo "The following ports are registered as necessary:"
716                 message_echo
717                 list=need.list
718                 ;;
719         noneed )
720                 message_echo "The following ports are registered as unnecessary:"
721                 message_echo
722                 list=noneed.list
723                 ;;
724         restored )
725                 message_echo "The following leaf, obsolete or unneeded ports had been once deleted but are to be or have been restored:"
726                 message_echo
727                 list=stage.loop_list/ports_to_restore
728                 pkgnamedb='moved_from obsolete initial'
729                 flag_filter_only_target=y
730                 ;;
731         deleted )
732                 message_echo "The following leaf, obsolete or unneeded ports are to be or have been deleted:"
733                 message_echo
734                 list=stage.loop_list/ports_to_delete
735                 pkgnamedb='moved_from obsolete initial'
736                 flag_filter_only_target=y
737                 ;;
738         leaves )
739                 if [ -z "$deptag" ]
740                 then
741                         message_echo "The following ports are all detected leaf ports:"
742                         list=leaf_ports
743                 else
744                         message_echo "The following ports are all $deptag leaf ports:"
745                         list=leaf_ports_to_delete.$deptag
746                 fi
747                 message_echo
748                 pkgnamedb='moved_from obsolete initial'
749                 flag_filter_only_target=y
750                 ;;
751         obsolete )
752                 if [ -z "$deptag" ]
753                 then
754                         message_echo "The following ports are all detected obsolete ports:"
755                         list=obsolete_ports.can_be_deleted
756                 else
757                         message_echo "The following ports are all $deptag obsolete ports:"
758                         list=obsolete_ports_to_delete.$deptag
759                 fi
760                 message_echo
761                 pkgnamedb='moved_from obsolete initial'
762                 flag_filter_only_target=y
763                 ;;
764         esac
765         database_query_show_single_list "$list" "$pkgnamedb" \
766                 "$flag_filter_skip_unchanged" "$flag_filter_only_target"
767 }
768
769 # ============= Check whether a port is registered in a list =============
770 database_query_exists_in_list ()
771 {
772         local origin subject deptag level tmp_list dbsuffix origin_esc
773         origin=$1
774         subject=$2
775         deptag=$3
776         level=$4
777         tmp_list=${TMPDIR}/database_query_exists_in_list:list
778         dbsuffix=$deptag.$level
779         origin_esc=`str_escape_regexp "$origin"`
780         case $subject in
781         todo )
782                 list=stage.loop_list/reinst_todo.remain
783                 [ ${DBDIR}/reinst_order.list -nt ${DBDIR}/$list ] && list=reinst_order.list
784                 ;;
785         done )
786                 list=success.$dbsuffix.list
787                 ;;
788         redo )
789                 list=todo_after_requirements_succeed.$dbsuffix.list
790                 ;;
791         resolved )
792                 list=manually_done.list
793                 ;;
794         inst_by_pkg )
795                 list=installation_complete_by_pkg.list
796                 ;;
797         inst_built_default )
798                 list=inst_by_port_with_default_conf.list
799                 ;;
800         inst_built_custom )
801                 list=inst_by_port_with_custom_conf.list
802                 ;;
803         failure )
804                 list=failed.list
805                 ;;
806         fossil )
807                 list=`ls "${DBDIR}"/fossil_pkgs/fossil_since_* | head -n 1`
808                 ;;
809         conflict )
810                 grep -v -E -f "${DBDIR}/ports_to_delete.grep_pattern_col1" "${DBDIR}/deleted_conflicts" 2> /dev/null \
811                         | grep -q -E "^${origin_esc}[[:space:]]"
812                 return
813                 ;;
814         taboo )
815                 list=taboo.all.list
816                 ;;
817         freeze )
818                 list=freeze.all.list
819                 ;;
820         need )
821                 list=need.list
822                 ;;
823         noneed )
824                 list=noneed.list
825                 ;;
826         restored )
827                 list=stage.loop_list/ports_to_restore
828                 ;;
829         deleted )
830                 list=stage.loop_list/ports_to_delete
831                 ;;
832         esac
833         grep -q -Fx "$origin" "${DBDIR}/$list" 2> /dev/null
834 }
835
836 # ============= Check whether the requirements of installed packages match the port configuration =============
837 database_query_dependency_matching ()
838 {
839         local origin pkg tmp_inst tmp_db
840         origin=$1
841         [ -d "${DBDIR}/requires/$origin" ] || return
842         tmp_inst=${TMPDIR}/database_query_dependency_matching.installed
843         tmp_db=${TMPDIR}/database_query_dependency_matching.configured
844         pkg=`database_build_get_new_pkgname "$origin"`
845         [ -n "$pkg" ] || return
846         pkg_info_e "$pkg" || return
847         pkg_info_qr "$pkg" | grep -v '^[[:space:]]*$' | sort -u > $tmp_inst
848         database_build_get_full_run_requirement_pkgs "$origin" > $tmp_db
849         diff "$tmp_inst" "$tmp_db" > /dev/null 2>/dev/null
850 }
851
852 # ============= Check whether any of the requirements are locked because being missing ports to freeze =============
853 database_query_are_requirements_not_locked ()
854 {
855         local origin
856         origin=$1
857         cat "${DBDIR}/requires/$origin/requirements.all.direct" 2> /dev/null | while read origin_requirement
858         do
859                 pkg_requirement=`pkgsys_get_installed_pkg_from_origin "$origin_requirement"` || :
860                 if grep -q -Fx "$origin_requirement" "${DBDIR}/freeze.all.list" 2> /dev/null
861                 then
862                         [ -n "$pkg_requirement" ] || return
863                 elif [ -z "$pkg_requirement" ]
864                 then
865                         database_query_are_requirements_not_locked "$origin_requirement" || return
866                 fi
867         done
868         :
869 }
870
871 # ============= Check whether any of progress is made in the current run =============
872 database_query_is_any_progress ()
873 {
874         [ `cat "${DBDIR}/new_success_in_current_run" 2> /dev/null | wc -l` -gt 0 ]
875 }
876
877 # ============= Get the all initial origins, separated by line feed =============
878 database_query_initial_orgins ()
879 {
880         local origin origin_init
881         origin=$1
882         if [ -e "${DBDIR}/moved_from/$origin/old_origs" ]
883         then
884                 for origin_init in `cat "${DBDIR}/moved_from/$origin/old_origs"`
885                 do
886                         [ -e "${DBDIR}/initial/$origin_init/installed_version" ] && echo "$origin_init"
887                 done
888         else
889                 [ -e "${DBDIR}/initial/$origin/installed_version" ] && echo "$origin"
890         fi
891         :
892 }