about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog3
-rw-r--r--Completion/Unix/Type/_canonical_paths31
2 files changed, 29 insertions, 5 deletions
diff --git a/ChangeLog b/ChangeLog
index 69c25383f..4774932ce 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,8 @@
 2008-03-27  Peter Stephenson  <pws@csr.com>
 
+	* 24757: Completion/Unix/Type/_canonical_paths: use
+	CHASE_LINKS and pwd to canonicalize the directory path.
+
 	* unposted: fix alias test in 24736 properly by replacing
 	"foo" everywhere.
 
diff --git a/Completion/Unix/Type/_canonical_paths b/Completion/Unix/Type/_canonical_paths
index 188b1d997..e4101dc47 100644
--- a/Completion/Unix/Type/_canonical_paths
+++ b/Completion/Unix/Type/_canonical_paths
@@ -36,20 +36,41 @@ typeset REPLY
 typeset -a matches files
 
 _canonical_paths_get_canonical_path() {
-  typeset newfile
+  typeset newfile dir
   typeset -A seen
 
   REPLY=$1
-  # Guard against loops.
+  # Resolve any trailing symbolic links, guarding against loops.
   while [[ -z ${seen[$REPLY]} ]]; do
     seen[$REPLY]=1
-    newfile=$(zstat +link $REPLY 2>/dev/null)
-    if [[ -n $newfile ]]; then
-      REPLY=$newfile
+    newfile=()
+    zstat -A newfile +link $REPLY 2>/dev/null
+    if [[ -n $newfile[1] ]]; then
+      REPLY=$newfile[1]
     else
       break
     fi
   done
+
+  # Canonicalise the directory path.  We may not be able to
+  # do this if we can't read all components.
+  if [[ -d $REPLY ]]; then
+    dir="$(unfunction chpwd
+           setopt CHASE_LINKS
+           cd $REPLY 2>/dev/null && pwd)"
+    if [[ -n $dir ]]; then
+      REPLY=$dir
+    fi
+  elif [[ $REPLY = */*[^/] && $REPLY != /[^/]# ]]; then
+    # Don't try this if there's a trailing slash or we're in
+    # the root directory.
+    dir="$(unfunction chpwd
+           setopt CHASE_LINKS
+           cd ${REPLY%/*} 2>/dev/null && pwd)"
+    if [[ -n $dir ]]; then
+      REPLY=$dir/${REPLY##*/}
+    fi
+  fi
 }