OSDN Git Service

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