Split out from my relocatable patch, because I think this is a useful tool for other (non-relocatable) cygports. Because the patch creates a new script, after applying the patch, don't forget to:
  (1) chmod +x bin/dorelsym
  (2) cvs add bin/dorelsym

What it does:

dorelsym creates symlink to install path but attempts to make the paths relative. For example:
   dorelsym ${D}/usr/share/terminfo ${D}/usr/lib/terminfo
will do
   (cd ${D}/usr/lib && ln -fs ../share/terminfo terminfo)

This is important when variables appear in both the target and symlink names, and you don't know the true relative path a priori.

From the script's own comments:
#   dosym ../share/terminfo ${D}/usr/lib/terminfo
# will work when you know the relative paths a priori, but
# not in the following case:
#   dosym ${D}${DATADIR}/mytarget ${D}${PREFIX}/bin/mysymlink
# because you don't know the relative path from ${PREFIX}/bin
# to ${DATADIR}.  That's what dorelsym is for -- it compares
# the actual values of target and symlink, computes the common
# prefix, and derives the relative path from (dir_of_symlink)
# to (target).


2007-01-05 Charles Wilson <...>

        * bin/dorelsym: new file.
        * bin/Makefile.am: add new file dorelsym

--
Chuck
Index: bin/Makefile.am
===================================================================
RCS file: /cvsroot/cygwin-ports/cygport/bin/Makefile.am,v
retrieving revision 1.4
diff -u -r1.4 Makefile.am
--- bin/Makefile.am     13 Dec 2006 03:19:11 -0000      1.4
+++ bin/Makefile.am     6 Jan 2007 04:56:58 -0000
@@ -20,6 +20,7 @@
        dolib \
        doman \
        domenu \
+       dorelsym \
        dosbin \
        dosym \
        \
diff -u /dev/null bin/dorelsym
--- /dev/null   2007-01-05 23:52:59.625000000 -0500
+++ bin/dorelsym        2007-01-05 23:52:04.109375000 -0500
@@ -0,0 +1,315 @@
+#!/bin/bash
+################################################################################
+#
+# dorelsym - creates symlink to install path
+#            but attempts to make the paths relative
+# That is:
+#   dosym ../share/terminfo ${D}/usr/lib/terminfo
+# will work when you know the relative paths a priori, but
+# not in the following case:
+#   dosym ${D}${DATADIR}/mytarget ${D}${PREFIX}/bin/mysymlink
+# because you don't know the relative path from ${PREFIX}/bin
+# to ${DATADIR}.  That's what dorelsym is for -- it compares
+# the actual values of target and symlink, computes the common
+# prefix, and derives the relative path from (dir_of_symlink)
+# to (target).
+#
+#  dorelsym [-d|-t|-e|-h] target symlink
+#    -h    print this help message
+#    -e    echo commands to screen (RELSYM_echo=yes)
+#    -t    trace execution         (RELSYM_trace=yes)
+#    -d    print debug information (RELSYM_debug=yes)
+#    -f    fake execution (only echo)
+#
+# Part of cygport - Cygwin packaging application
+# Copyright (C) 2007 Charles Wilson
+# Distributed under the terms of the GNU General Public License v2
+#
+################################################################################
+set -e
+
+RELSYM_common=""
+RELSYM_from=""
+RELSYM_to=""
+RELSYM_debug_msg()
+{
+       if [ -n "${RELSYM_debug}" ]
+       then
+               echo "[EMAIL PROTECTED]" 1>&2
+       fi
+}
+RELSYM_trace_msg()
+{
+       if [ -n "${RELSYM_trace}" -o -n "${RELSYM_debug}" ]
+       then
+               echo "[EMAIL PROTECTED]" 1>&2
+       fi
+}
+RELSYM_echo_msg()
+{
+       if [ -n "${RELSYM_echo}" ]
+       then
+               echo "[EMAIL PROTECTED]" 1>&2
+       fi
+}
+
+compute_common_prefix()
+{
+       local from="${1}"
+       local to="${2}"
+       local -a fromA
+       local -a toA
+       local -i fromN
+       local -i toN
+       local differ
+       local common
+       local from_suffix
+       local to_suffix
+       local isAbs;
+
+       if [ -z "${1}" -o -z "${2}" ]
+       then
+               echo "Error: empty argument(s) for compute_common_prefix" 1>&2
+               exit 1
+       fi
+
+       isAbs=""
+       case "${from}" in
+               /*  ) from="${from#/}" ; isAbs=yes ;;
+               ./* ) cwd=$(pwd) ; from="${cwd#/}/${from#./}" ;;
+               *   ) cwd=$(pwd) ; from="${cwd#/}/${from}" ;;
+       esac
+       case "${to}" in
+               /* ) to="${to#/}" ; isAbs=yes ;;
+               ./* ) cwd=$(pwd) ; to="${cwd#/}/${to#./}" ;;
+               *   ) cwd=$(pwd) ; to="${cwd#/}/${to}" ;;
+       esac
+
+       oldIFS="${IFS}"
+       IFS=/
+       fromA=(${from})
+       toA=(${to})
+       IFS="${oldIFS}"
+
+       fromN=0
+       toN=0
+       differ=""
+       common=""
+       while test -z "${differ}" && (( fromN < [EMAIL PROTECTED] )) && (( toN 
< [EMAIL PROTECTED] ))
+       do
+               while test -z "${fromA[${fromN}]}" && (( fromN < [EMAIL 
PROTECTED] ))
+               do
+                       (( fromN++ ))
+               done
+
+               while test -z "${toA[${toN}]}" && (( toN < [EMAIL PROTECTED] ))
+               do
+                       (( toN++ ))
+               done
+
+               if (( fromN >= [EMAIL PROTECTED] )) || (( toN >= [EMAIL 
PROTECTED] ))
+               then
+                       break
+               fi
+
+               RELSYM_debug_msg "from (${fromN}) ${fromA[${fromN}]}"
+               RELSYM_debug_msg "to   (${toN}) ${toA[${toN}]}"
+               if [ "${fromA[${fromN}]}" == "${toA[${toN}]}" ]
+               then
+                       common="${common}/${fromA[${fromN}]}";
+                       (( fromN++ ))
+                       (( toN++ ))
+               else
+                       differ=yes
+               fi
+       done
+       
+       from_suffix=""
+       while (( fromN < [EMAIL PROTECTED] ))
+       do
+               while test -z "${fromA[${fromN}]}" && (( fromN < [EMAIL 
PROTECTED] ))
+               do
+                       (( fromN++ ))
+               done
+
+               if (( fromN >= [EMAIL PROTECTED] ))
+               then
+                       break
+               fi
+               RELSYM_debug_msg "fromS (${fromN}) ${fromA[${fromN}]}"
+               from_suffix="${from_suffix}/${fromA[${fromN}]}"
+               (( fromN++ ))
+       done
+
+       to_suffix=""
+       while (( toN < [EMAIL PROTECTED] ))
+       do
+               while test -z "${toA[${toN}]}" && (( toN < [EMAIL PROTECTED] ))
+               do
+                       (( toN++ ))
+               done
+
+               if (( toN >= [EMAIL PROTECTED] ))
+               then
+                       break
+               fi
+               RELSYM_debug_msg "toS   (${toN}) ${toA[${toN}]}"
+               to_suffix="${to_suffix}/${toA[${toN}]}"
+               (( toN++ ))
+       done
+
+       case "${common}" in
+               /* )  ;;
+               *)
+                       if [ -n "${common}" ]
+                       then
+                               common="/${common}"
+                       fi
+                       ;;
+       esac
+
+       RELSYM_trace_msg "commonPrefix: ${common}"
+       RELSYM_trace_msg "fromSuffix  : ${from_suffix}"
+       RELSYM_trace_msg "toSuffix    : ${to_suffix}"
+
+       RELSYM_common="${common}"
+       RELSYM_from="${from_suffix}"
+       RELSYM_to="${to_suffix}"
+}
+
+RELSYM_dir=""
+RELSYM_tgt=""
+RELSYM_sym=""
+compute_relative_path() {
+       local from_suffix="${RELSYM_from}"
+       local to_suffix="${RELSYM_to}"
+       local common="${RELSYM_common}"
+       local -a fromA
+       local -a toA
+       local -i fromN
+       local -i toN
+       local rel
+
+
+       case "${from_suffix}" in
+               /* ) from_suffix="${from_suffix#/}" ;;
+               * ) ;;
+       esac
+       case "${to_suffix}" in
+               /* ) to_suffix="${to_suffix#/}" ;;
+               * ) ;;
+       esac
+
+       if [ -z "${common}" ]
+       then
+               RELSYM_tgt="/${to_suffix}"
+               RELSYM_sym="${from_suffix##*/}"
+               RELSYM_dir="/${from_suffix%/*}"
+               return
+       fi
+
+       oldIFS="${IFS}"
+       IFS=/
+       fromA=(${from_suffix})
+       toA=(${to_suffix})
+       IFS="${oldIFS}"
+
+       if (( [EMAIL PROTECTED] == 0 )) && (( [EMAIL PROTECTED] == 0 ))
+       then
+               echo "Refusing to create circular link: ${common} -> ${common}" 
1>&2
+               exit 1
+       fi
+       if (( [EMAIL PROTECTED] == 0 ))
+       then
+               echo "Refusing to create circular link: ${common} -> 
${common}/${to_suffix}" 1>&2
+               exit 1
+       fi
+       if (( [EMAIL PROTECTED] == 0 ))
+       then
+               echo "Refusing to create circular link: 
${common}/${from_suffix} -> ${common}" 1>&2
+               exit 1
+       fi
+
+       rel=""
+       [EMAIL PROTECTED]
+       while (( fromN > 0 ))
+       do
+               rel="../${rel}"
+               RELSYM_debug_msg "rel: (${fromN}) ${fromA[${fromN}-1]} ${rel}"
+               (( fromN-- ))
+       done
+
+       tgt="${rel}${to_suffix}"
+       sym="${from_suffix##*/}"
+       dir="${RELSYM_common}/${from_suffix%/*}"
+
+       RELSYM_trace_msg "dir         : ${dir}"
+       RELSYM_trace_msg "tgt         : ${tgt}"
+       RELSYM_trace_msg "sym         : ${sym}"
+
+       RELSYM_tgt="${tgt}"
+       RELSYM_sym="${sym}"
+       RELSYM_dir="${dir}"
+}
+
+RELSYM_help()
+{
+       echo "$0 [-d|-t|-e|-h] target symlink"
+       echo " -h    print this help message"
+       echo " -e    echo commands to screen (RELSYM_echo=yes)"
+       echo " -t    trace execution         (RELSYM_trace=yes)"
+       echo " -d    print debug information (RELSYM_debug=yes)"
+       echo " -f    fake execution (only echo)"
+}
+while getopts 'dtefh' OPT_LETTER
+do
+       case "${OPT_LETTER}" in
+       "d" ) RELSYM_debug=yes ;;
+       "t" ) RELSYM_trace=yes ;;
+       "e" ) RELSYM_echo=yes ;;
+       "f" ) RELSYM_echo=yes ; RELSYM_fake=yes ;;
+       "h" ) RELSYM_help ; exit 0 ;;
+       esac
+done
+used_up=`expr $OPTIND - 1`
+shift $used_up
+
+
+if (( $# < 2 ))
+then
+       echo "Not enough arguments: must specify target and symlink"
+       RELSYM_help
+       exit 1
+fi
+if (( $# > 2 ))
+then
+       echo "Too many arguments"
+       RELSYM_help
+       exit 1
+fi
+
+
+###############
+## real work ##
+###############
+
+## c_c_p from(sym) to(tgt), but cmdline args are tgt(to) sym(from)
+## so, need to swap:
+compute_common_prefix "${2}" "${1}"
+compute_relative_path
+
+if [ ! -d "${RELSYM_dir}" ]
+then
+       RELSYM_echo_msg "mkdir -p \"${RELSYM_dir}\""
+       if [ -z "${RELSYM_fake}" ]
+       then
+               mkdir -p "${RELSYM_dir}"
+       fi
+fi
+
+RELSYM_echo_msg "(cd \"${RELSYM_dir}\" && ln -fs \"${RELSYM_tgt}\" 
\"${RELSYM_sym}\")"
+if [ -z "${RELSYM_fake}" ]
+then
+       (cd "${RELSYM_dir}" && ln -fs "${RELSYM_tgt}" "${RELSYM_sym}")
+fi
+

--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Problem reports:       http://cygwin.com/problems.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/

Reply via email to