OSDN Git Service

Version 3.0.5+toward_3.1.0_20140712053146
[portsreinstall/current.git] / lib / libpkgsys.sh
index 22f99ee..b2bc37e 100644 (file)
@@ -2,19 +2,35 @@
 # ==============================================================================
 # portsreinstall library script
 # - Wrappers for hiding version differences in the Ports/Packages system -
-# Copyright (C) 2013 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
+# Copyright (C) 2013-2014 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
 # This software is distributed under the 2-Clause BSD License.
 # ==============================================================================
 
 # ============= Variables =============
-PKGSYS_USE_PKGNG=no    # no: legacy pkg_* tools, yes: the new generation package (pkgng)
-PKGSYS_CMD_PKG_INFO='pkg_info' # Corresponding command for pkg_info
-PKGSYS_CMD_PKG_CREATE='pkg_create'     # Corresponding command for pkg_create
-PKGSYS_CMD_PKG_DELETE='pkg_delete'     # Corresponding command for pkg_delete
-PKGSYS_CMD_PKG_ADD='pkg_add'   # Corresponding command for pkg_add
+PKGSYS_USE_PKGNG=yes   # no: legacy pkg_* tools, yes: the new generation package (pkgng)
+PKGSYS_CMD_PKG_INFO='pkg info' # Corresponding command for pkg_info
+PKGSYS_CMD_PKG_CREATE='pkg create'     # Corresponding command for pkg_create
+PKGSYS_CMD_PKG_DELETE='pkg delete'     # Corresponding command for pkg_delete
+PKGSYS_CMD_PKG_ADD='pkg add'   # Corresponding command for pkg_add
 PKGSYS_AVR_REFETCH_TIMES_PER_SITE=1    # Average number (integer) of retrials for retrieving package or distfiles per mirror site
 PKGSYS_AVR_REFETCH_TIMES_FOR_CHKSUMERR=2       #  Number (integer) of retrials for check sum error in retrieving a package
 
+# ============= Check implementation of the ports tree =============
+pkgsys_chk_ports_tree_implementation ()
+{
+       local var tmp_work
+       if [ ! -d "${PORTSDIR}" ]
+       then
+               message_echo "ERROR: Ports directory ${PORTSDIR} is not found." >&2
+               exit 1
+       fi
+       if [ ! -e "${PORTSDIR}/Makefile" -o ! -e "${PORTSDIR}/Mk/bsd.port.mk" ]
+       then
+               message_echo "ERROR: Ports tree ${PORTSDIR} is missing, broken or incompatible." >&2
+               exit 1
+       fi
+}
+
 # ============= System defined value for the ports/packages =============
 pkgsys_sysvar ()
 {
@@ -23,7 +39,7 @@ pkgsys_sysvar ()
        tmp_work=${TMPDIR}/pkgsys_sysvar:work
        rm -rf "$tmp_work"
        mkdir "$tmp_work"
-       make -C "$tmp_work" -f "${PORTSDIR}/Mk/bsd.port.mk" -V "$var"
+       make -C "$tmp_work" -f "${PORTSDIR}/Mk/bsd.port.mk" -V "$var" 2> /dev/null
 }
 
 # ============= Get the file name of package check sum file =============
@@ -147,12 +163,22 @@ pkgsys_fetch_legacy_remote ()
        [ -d "${PKGREPOSITORY}" ] || mkdir -p "${PKGREPOSITORY}"
        if [ -e "${PKGREPOSITORY}/$pkg.tbz" ]
        then
-               fetchedMD5=`md5 "${PKGREPOSITORY}/$pkg.tbz" | sed -E "s/^[^=]*=[[:space:]]*(.*)/\1/"`
-               if [ "x$fetchedMD5" = "x$validMD5" ]
+               if [ -e "${PKGREPOSITORY}/$pkg.md5=$validMD5.tbz" ]
+               then
+                       fetchedMD5=`md5 "${PKGREPOSITORY}/$pkg.md5=$validMD5.tbz" | sed -E "s/^[^=]*=[[:space:]]*(.*)/\1/"`
+                       [ "x$fetchedMD5" = "x$validMD5" ] || rm "${PKGREPOSITORY}/$pkg.md5=$fetchedMD5.tbz"
+               fi
+               if [ -e "${PKGREPOSITORY}/$pkg.md5=$validMD5.tbz" ]
                then
-                       needs_fetch=no
+                       ln -f "${PKGREPOSITORY}/$pkg.md5=$fetchedMD5.tbz" "${PKGREPOSITORY}/$pkg.tbz"
                else
-                       mv "${PKGREPOSITORY}/$pkg.tbz" "${PKGREPOSITORY}/$pkg.md5=$fetchedMD5.tbz"
+                       fetchedMD5=`md5 "${PKGREPOSITORY}/$pkg.tbz" | sed -E "s/^[^=]*=[[:space:]]*(.*)/\1/"`
+                       if [ "x$fetchedMD5" = "x$validMD5" ]
+                       then
+                               needs_fetch=no
+                       else
+                               mv "${PKGREPOSITORY}/$pkg.tbz" "${PKGREPOSITORY}/$pkg.md5=$fetchedMD5.tbz"
+                       fi
                fi
        fi
        if [ $needs_fetch = yes ]
@@ -214,10 +240,16 @@ pkg_is_dependency_of_a_legacypkg_latest ()
        :
 }
 
+# ============= Check whether legacy package tools are available =============
+pkgsys_is_legacy_tool_available ()
+{
+       which -s pkg_info
+}
+
 # ============= Define wrapper commands for hiding the differences between pkg_* tools and pkgng =============
 pkgsys_def_pkgtools ()
 {
-       if [ "${DBDIR}/WITH_PKGNG" -nt /etc/make.conf ]
+       if [ "${DBDIR}/WITH_PKGNG" -nt /etc/make.conf -o \( -e "${DBDIR}/WITH_PKGNG" -a ! -e /etc/make.conf \) ]
        then
                PKGSYS_USE_PKGNG=`cat "${DBDIR}/WITH_PKGNG"`
        else
@@ -237,7 +269,14 @@ pkgsys_def_pkgtools ()
                PKGSYS_CMD_PKG_ADD='pkg add'
                pkg_is_tool_available ()
                {
-                       which -a pkg | grep -v '^/usr/sbin/pkg$' | grep -q '/sbin/pkg$'
+                       if [ -x /usr/sbin/pkg ]
+                       then
+                               pkg -N 2> /dev/null && return
+                               env ASSUME_ALWAYS_YES=yes pkg bootstrap -f
+                               pkg_is_tool_available
+                       else
+                               which -s pkg && return
+                       fi
                }
                pkg_info_Ea ()
                {
@@ -253,7 +292,7 @@ pkgsys_def_pkgtools ()
 #              }
                pkg_info_qoX ()
                {
-                       pkg info -qoX "$@" 2> /dev/null
+                       pkg info -qox "$@" 2> /dev/null
                }
                pkg_info_qO ()
                {
@@ -297,6 +336,12 @@ pkgsys_def_pkgtools ()
                        pkg=$1
                        pkg check -s "$pkg" 2> /dev/null
                }
+               pkg_which ()
+               {
+                       local filepath
+                       filepath=$1
+                       pkg which -q "$filepath" 2> /dev/null
+               }
                pkg_info_gen_pkg_origin_table ()
                {
                        pkg query -g '%n-%v\t%o' \* 2> /dev/null > ${DBDIR}/installed_ports:pkg_vs_origin.tbl
@@ -393,6 +438,7 @@ pkgsys_def_pkgtools ()
                        then
                                pkg_inst_remote "$pkg" "$mode" && return
                        fi
+                       pkgsys_is_legacy_tool_available || return
                        message_echo "INFO: Trying to use a legacy package and convert it to pkgng."
                        pkgsys_fetch_legacy_remote "$pkg" || return
                        pkgarc=`pkgsys_fetch_legacy_remote__fetched_pkg`
@@ -444,23 +490,42 @@ pkgsys_def_pkgtools ()
                }
                pkg_rescue_tools ()
                {
-                       local packagepath checksumpath pkgname
+                       local packagepath checksumpath pkgname is_successful
                        packagepath=`pkgsys_get_backup_pkg ports-mgmt/pkg` && \
                                pkg_add_tools "$packagepath" && return
-                       [ -x /usr/local/sbin/pkg ] && return
-                       message_echo "WARNING: WITH_PKGNG is set, but pkgng is missing. It is installed now." >&2
-                       [ -x /usr/sbin/pkg ] && /usr/sbin/pkg && return
+                       pkg_is_tool_available && return
+                       message_echo "WARNING: WITH_PKGNG is set, but pkgng is still missing. It is installed now." >&2
                        pkgsys_ready_checksum_file || return
+                       message_echo "INFO: Installing pkgng by legacy package tool."
                        checksumpath=`pkgsys_ready_checksum_file__fetched_file`
                        pkgname=`sed 's/^MD5[[:space:]]*(//;s/\.tbz)[[:space:]]*=[^=]*$//' "$checksumpath" \
                                | grep -m 1 -E -e "^pkg-[0-9]"` || :
-                       [ -z "$pkgname" ] && pkg_inst_remote_wild "$pkgname" nodepschk && return
-                       make -C "${PORTSDIR}/ports-mgmt/pkg" install clean && return
-                       message_echo "ERROR: WITH_PKGNG is set, but pkgng is missing. It is installed now." >&2
-                       :
+                       [ -n "$pkgname" ] && pkg_inst_remote_wild "$pkgname" nodepschk && return
+                       message_echo "INFO: Failed by package, so installing pkgng by port."
+                       grep -v '^[[:space:]]*WITH_PKGNG=' /etc/make.conf > ${TMPDIR}/make.conf
+                       echo WITHOUT_PKGNG=yes >> ${TMPDIR}/make.conf
+                       ( set -e
+                               unset WITH_PKGNG
+                               unset WITHOUT_PKGNG
+                               
+                               message_echo "INFO: Attempting deinstallation of ports-mgmt/pkg to make sure."
+                               env __MAKE_CONF="${TMPDIR}/make.conf" make -C "${PORTSDIR}/ports-mgmt/pkg" deinstall || :
+                               message_echo "INFO: Attempting (re)installation by ports-mgmt/pkg."
+                               env __MAKE_CONF="${TMPDIR}/make.conf" make -C "${PORTSDIR}/ports-mgmt/pkg" reinstall clean
+                       ) && {
+                               pkg2ng || :
+                               pkg_is_tool_available
+                       }
                }
-               pkg_rescue_tools
+               if ! pkg_rescue_tools
+               then
+                       message_echo "WARNING: Pkgng is still missing, but continuing for the time being." >&2
+               fi
                pkg_loadconf
+       elif ! pkgsys_is_legacy_tool_available
+       then
+               message_echo "ERROR: Pkgng is disabled although the legacy packages tools are unavailable. Resolve the problem manually." >&2
+               exit 1
        else
                unset WITH_PKGNG
                PKGSYS_USE_PKGNG=no
@@ -470,7 +535,7 @@ pkgsys_def_pkgtools ()
                PKGSYS_CMD_PKG_ADD='pkg_add'
                pkg_is_tool_available ()
                {
-                       :
+                       pkgsys_is_legacy_tool_available
                }
                pkg_info_Ea ()
                {
@@ -530,6 +595,12 @@ pkgsys_def_pkgtools ()
                        pkg=$1
                        pkg_info -qg "$pkg" 2> /dev/null
                }
+               pkg_which ()
+               {
+                       local filepath
+                       filepath=$1
+                       pkg_info -qW "$filepath" 2> /dev/null
+               }
                pkg_info_gen_pkg_origin_table ()
                {
                        pkg_info -aE 2> /dev/null | while read pkg
@@ -604,8 +675,8 @@ pkgsys_pkg_info_qO_init ()
        origin=$1
        tmppkg=${TMPDIR}/pkgsys_pkg_info_qO_init::pkg
        origin_regexp=`str_escape_regexp "$origin"`
-       { sed -n -E "/[[:space:]]$origin_regexp$/p" "${DBDIR}/installed_ports:pkg_vs_origin.tbl" 2> /dev/null || :; } \
-               | cut -f 1 > $tmppkg
+       sed -n -E "/[[:space:]]$origin_regexp$/p" "${DBDIR}/installed_ports:pkg_vs_origin.tbl" 2> /dev/null \
+               | cut -f 1 > $tmppkg || :
        npkgs=`wc -l < $tmppkg`
        if [ $npkgs -gt 0 ]
        then
@@ -638,17 +709,21 @@ pkgsys_init_pkg_orig_by_ambiguous_matching ()
        ambsuffix=
        norigins=0
        len_pkg=`echo -n "$pkg" | wc -c`
-       while [ $len_pkg -gt 0 ]
-       do
-               pkg_regexp=`str_escape_regexp "$pkg"`$ambsuffix
-               grep -E "^${pkg_regexp}[[:space:]]" "${DBDIR}/installed_ports:pkg_vs_origin.tbl" 2> /dev/null \
-                       | cut -f 2 > $tmporigin
-               norigins=`wc -l < $tmporigin`
-               [ $norigins -gt 0 ] && break
-               len_pkg=$(($len_pkg-1))
-               pkg=`echo -n "$pkg" | head -c $len_pkg`
-               ambsuffix='[a-zA-Z0-9.,_+-]*'
-       done
+       if [ $len_pkg -gt 0 ]
+       then
+               while :
+               do
+                       pkg_regexp=`str_escape_regexp "$pkg"`$ambsuffix
+                       grep -E "^${pkg_regexp}[[:space:]]" "${DBDIR}/installed_ports:pkg_vs_origin.tbl" 2> /dev/null \
+                               | cut -f 2 > $tmporigin
+                       norigins=`wc -l < $tmporigin`
+                       [ $norigins -gt 0 ] && break
+                       ambsuffix='[a-zA-Z0-9.,_+-]*'
+                       len_pkg=$(($len_pkg-1))
+                       [ $len_pkg -gt 0 ] || break
+                       pkg=`echo -n "$pkg" | head -c $len_pkg`
+               done
+       fi
        [ $norigins -eq 1 ] || return
        cat "$tmporigin"
 }
@@ -705,7 +780,7 @@ pkgsys_eval_ports_glob ()
                shift
                expr "x$glob" : '^x-' > /dev/null 2>&1 && continue
                glob_regexp=`str_convert_portsglob_to_regexp_pattern "$glob"`
-               if expr "$glob" : '[^/][^/]*\/[^/][^/]*$' > /dev/null 2>&1
+               if expr "$glob" : '.*/' > /dev/null 2>&1
                then
                        grep -E "$glob_regexp" "$origlist" 2>&1 || :
                        {
@@ -713,7 +788,7 @@ pkgsys_eval_ports_glob ()
                                cut -f 2 "${DBDIR}/installed_ports:pkg_vs_origin.tbl" 2> /dev/null
                        } | grep -E "$glob_regexp" 2>&1 || :
                else
-                       if expr "$glob" : '^[a-z][a-zA-Z0-9+-]*[a-zA-Z0-9+]$' > /dev/null 2>&1 && \
+                       if expr "$glob" : '^[a-z][a-zA-Z0-9_.+-]*[a-zA-Z0-9_.+]$' > /dev/null 2>&1 && \
                                [ `expr "$glob" : '.*-[0-9]' 2>&1` -eq 0 ]
                        then
                                glob_regexp2=`expr "$glob_regexp" : '\(.*\)\$$' 2>&1`'-[0-9]'
@@ -726,8 +801,8 @@ pkgsys_eval_ports_glob ()
                                sed -n ${index}p "$origlist"
                        done || :
                        glob_regexp2=`expr "$glob_regexp" : '\(.*\)\$$' 2>&1`'[[:space:]]'
-                       { sed -n -E "/$glob_regexp2/p" "${DBDIR}/installed_ports:pkg_vs_origin.tbl" 2> /dev/null || :; } \
-                               | cut -f 2
+                       sed -n -E "/$glob_regexp2/p" "${DBDIR}/installed_ports:pkg_vs_origin.tbl" 2> /dev/null \
+                               | cut -f 2 || :
                        pkg_info_qoX "$glob_regexp" || :
                fi
        done | sort -u
@@ -849,7 +924,7 @@ pkgsys_eval_ports_glob_even_if_nonexistent ()
        glob_pattern=$1
        {
                pkgsys_eval_ports_glob "$glob_pattern" 2> /dev/null || :
-               echo "$glob_pattern" | grep '^[a-z][a-z]*/[a-zA-Z0-9_+-][a-zA-Z0-9_+-]*$' || :
+               echo "$glob_pattern" | grep '^[a-z][a-z]*/[a-zA-Z0-9_.+-][a-zA-Z0-9_.+-]*$' || :
        } | grep -v -e '^$' | sort -u
 }
 
@@ -911,7 +986,7 @@ pkgsys_get_conflicting_pkgs_patterns ()
                conflicts=$conflicts' '`database_query_get_makevar_val "$origin" CONFLICTS_INSTALL`
                ;;
        esac
-       echo "$conflicts"
+       echo "$conflicts" | tr ' ' '\n' | grep -v '^$' || :
 }      
 
 # ============= Get conflicting installed packages of a port =============
@@ -932,7 +1007,7 @@ pkgsys_chk_conflict_by_a_pkg ()
        local mode origin pkg tmp_conflicts_ptn
        mode=$1
        origin=$2
-       pkg=$2
+       pkg=$3
        tmp_conflicts_ptn=${TMPDIR}/pkgsys_chk_conflict_by_a_pkg::conflicts_ptn
        pkgsys_get_conflicting_pkgs_patterns "$mode" "$origin" \
                | str_convert_glob_to_regexp_pattern > $tmp_conflicts_ptn
@@ -942,11 +1017,46 @@ pkgsys_chk_conflict_by_a_pkg ()
 # ============= Check whether installed files are lost or broken for a package =============
 pkgsys_sanitychk_pkgcontents ()
 {
-       local pkg tmp_sanity origin
+       local pkg var_is_reinstall_encouraged _is_reinstall_encouraged tmp_sanity nlines iline src filename icol filename_esc pkg_owner origin
        pkg=$1
+       var_is_reinstall_encouraged=$2
        tmp_sanity=${TMPDIR}/pkgsys_sanitychk_pkgcontents:sanity
        pkg_check_sanity "$pkg" > $tmp_sanity || :
+       eval "$var_is_reinstall_encouraged=no"
        [ `wc -l < $tmp_sanity` -eq 0 ] && return
+       nlines=`wc -l < $tmp_sanity`
+       iline=1
+       _is_reinstall_encouraged=no
+       while [ $iline -le $nlines ]
+       do
+               src=`sed -n ${iline}p "$tmp_sanity"`
+               iline=$(($iline+1))
+               filename=`echo "$src" | cut -d ' ' -f 1`
+               icol=2
+               until [ -e "$filename" -o "$filename" = "$src" ]
+               do
+                       filename="$filename "`echo "$src" | cut -d ' ' -f $icol`
+               done
+               [ -e "$filename" ] || continue
+               if expr "$filename" : '.*/include/.*' > /dev/null
+               then
+                       _is_reinstall_encouraged=yes
+                       break
+               fi
+               filename_esc=`str_escape_regexp "$filename"`
+               if file "$filename" | sed -E "s/^$filename_esc:[[:space:]]//" | grep -q '^ELF '
+               then
+                       _is_reinstall_encouraged=yes
+                       break
+               fi
+               pkg_owner=`pkg_which "$filename"`
+               if [ "$pkg" != "$pkg_owner" ]
+               then
+                       _is_reinstall_encouraged=yes
+                       break
+               fi
+       done
+       eval "$var_is_reinstall_encouraged=\$_is_reinstall_encouraged"
        origin=`pkg_info_qo "$pkg"`
        if [ $opt_batch_mode = no ]
        then
@@ -956,7 +1066,7 @@ pkgsys_sanitychk_pkgcontents ()
        else
                pkg_replace=`str_escape_replaceval "$pkg"`
                origin_replace=`str_escape_replaceval "$origin"`
-               sed "s/^/$pkg_replace\\\\$origin_replace\\\\/" "$tmp_sanity" | tr '\\' '\t'
+               sed "s/^/$pkg_replace\\\\$origin_replace\\\\$_is_reinstall_encouraged\\\\/" "$tmp_sanity" | tr '\\' '\t'
        fi
        return 1
 }