This is the mail archive of the
cygwin
mailing list for the Cygwin project.
[patch] cygport-0.2.9 tool for generating relative symlinks
- From: Charles Wilson <cygwin at cwilson dot fastmail dot fm>
- To: cygwin at cygwin dot com
- Date: Mon, 05 Feb 2007 17:00:37 -0500
- Subject: [patch] cygport-0.2.9 tool for generating relative symlinks
- References: <announce.45C6C93F.706@users.sourceforge.net>
Forward port to latest release.
For further history and justifiation of this patch, see
http://cygwin.com/ml/cygwin/2007-01/msg00114.html and follow the
embedded links and threads.
--
Chuck
2007-02-05 Charles Wilson <...>
* bin/dorelsym: new file.
* bin/Makefile.am: add new file dorelsym
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 5 Feb 2007 21:37:33 -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
+
--
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/