X-Spam-Check-By: sourceware.org Message-ID: <459F2DAB.6000000@cwilson.fastmail.fm> Date: Sat, 06 Jan 2007 00:03:39 -0500 From: Charles Wilson User-Agent: Thunderbird 1.5.0.9 (Windows/20061207) MIME-Version: 1.0 To: cygwin AT cygwin DOT com Subject: [patch] cygport-0.2.7 tool for generating relative symlinks Content-Type: multipart/mixed; boundary="------------070600070704040503030605" Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT cygwin DOT com Mail-Followup-To: cygwin AT cygwin DOT com Delivered-To: mailing list cygwin AT cygwin DOT com --------------070600070704040503030605 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit 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 --------------070600070704040503030605 Content-Type: text/plain; name="cygport-dorelsym.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="cygport-dorelsym.patch" 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 "${@}" 1>&2 + fi +} +RELSYM_trace_msg() +{ + if [ -n "${RELSYM_trace}" -o -n "${RELSYM_debug}" ] + then + echo "${@}" 1>&2 + fi +} +RELSYM_echo_msg() +{ + if [ -n "${RELSYM_echo}" ] + then + echo "${@}" 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 < ${#fromA[@]} )) && (( toN < ${#toA[@]} )) + do + while test -z "${fromA[${fromN}]}" && (( fromN < ${#fromA[@]} )) + do + (( fromN++ )) + done + + while test -z "${toA[${toN}]}" && (( toN < ${#toA[@]} )) + do + (( toN++ )) + done + + if (( fromN >= ${#fromA[@]} )) || (( toN >= ${#toA[@]} )) + 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 < ${#fromA[@]} )) + do + while test -z "${fromA[${fromN}]}" && (( fromN < ${#fromA[@]} )) + do + (( fromN++ )) + done + + if (( fromN >= ${#fromA[@]} )) + then + break + fi + RELSYM_debug_msg "fromS (${fromN}) ${fromA[${fromN}]}" + from_suffix="${from_suffix}/${fromA[${fromN}]}" + (( fromN++ )) + done + + to_suffix="" + while (( toN < ${#toA[@]} )) + do + while test -z "${toA[${toN}]}" && (( toN < ${#toA[@]} )) + do + (( toN++ )) + done + + if (( toN >= ${#toA[@]} )) + 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 (( ${#fromA[@]} == 0 )) && (( ${#toA[@]} == 0 )) + then + echo "Refusing to create circular link: ${common} -> ${common}" 1>&2 + exit 1 + fi + if (( ${#fromA[@]} == 0 )) + then + echo "Refusing to create circular link: ${common} -> ${common}/${to_suffix}" 1>&2 + exit 1 + fi + if (( ${#toA[@]} == 0 )) + then + echo "Refusing to create circular link: ${common}/${from_suffix} -> ${common}" 1>&2 + exit 1 + fi + + rel="" + fromN=${#fromA[@]}-1 + 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 + --------------070600070704040503030605 Content-Type: text/plain; charset=us-ascii -- 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/ --------------070600070704040503030605--