This is the mail archive of the cygwin mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] cygport-0.2.9 tool for generating relative symlinks


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/

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]