* net/tramp.el (tramp-check-for-regexp): Avoid "Args out of range"
[bpt/emacs.git] / lisp / net / tramp.el
index 58506ce..6710c8a 100644 (file)
@@ -1,6 +1,6 @@
 ;;; tramp.el --- Transparent Remote Access, Multiple Protocol
 
-;; Copyright (C) 1998-2012 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2013 Free Software Foundation, Inc.
 
 ;; Author: Kai Großjohann <kai.grossjohann@gmx.net>
 ;;         Michael Albinus <michael.albinus@gmx.de>
@@ -403,6 +403,7 @@ interpreted as a regular expression which always matches."
 (defcustom tramp-save-ad-hoc-proxies nil
   "Whether to save ad-hoc proxies persistently."
   :group 'tramp
+  :version "24.3"
   :type 'boolean)
 
 (defcustom tramp-restricted-shell-hosts-alist
@@ -413,7 +414,7 @@ This is a list of regular expressions, which denote hosts running
 a registered shell like \"rbash\".  Those hosts can be used as
 proxies only, see `tramp-default-proxies-alist'.  If the local
 host runs a registered shell, it shall be added to this list, too."
-  :version "24.2"
+  :version "24.3"
   :group 'tramp
   :type '(repeat (regexp :tag "Host regexp")))
 
@@ -1352,8 +1353,7 @@ ARGS to actually emit the message (if applicable)."
                         "tramp-debug-message"
                         "tramp-error"
                         "tramp-error-with-buffer"
-                        "tramp-message"
-                        "tramp-with-progress-reporter")
+                        "tramp-message")
                       t)
                      "$")
                     fn)))
@@ -1497,7 +1497,7 @@ If VAR is nil, then we bind `v' to the structure and `method', `user',
     (when (string-match message (or (current-message) ""))
       (tramp-compat-funcall 'progress-reporter-update reporter value))))
 
-(defmacro tramp-with-progress-reporter (vec level message &rest body)
+(defmacro with-tramp-progress-reporter (vec level message &rest body)
   "Executes BODY, spinning a progress reporter with MESSAGE.
 If LEVEL does not fit for visible messages, or if this is a
 nested call of the macro, there are only traces without a visible
@@ -1526,7 +1526,42 @@ progress reporter."
        (tramp-message ,vec ,level "%s...done" ,message))))
 
 (tramp-compat-font-lock-add-keywords
- 'emacs-lisp-mode '("\\<tramp-with-progress-reporter\\>"))
+ 'emacs-lisp-mode '("\\<with-tramp-progress-reporter\\>"))
+
+(defmacro with-tramp-file-property (vec file property &rest body)
+  "Check in Tramp cache for PROPERTY, otherwise execute BODY and set cache.
+FILE must be a local file name on a connection identified via VEC."
+  `(if (file-name-absolute-p ,file)
+      (let ((value (tramp-get-file-property ,vec ,file ,property 'undef)))
+       (when (eq value 'undef)
+         ;; We cannot pass @body as parameter to
+         ;; `tramp-set-file-property' because it mangles our
+         ;; debug messages.
+         (setq value (progn ,@body))
+         (tramp-set-file-property ,vec ,file ,property value))
+       value)
+     ,@body))
+
+(put 'with-tramp-file-property 'lisp-indent-function 3)
+(put 'with-tramp-file-property 'edebug-form-spec t)
+(tramp-compat-font-lock-add-keywords
+ 'emacs-lisp-mode '("\\<with-tramp-file-property\\>"))
+
+(defmacro with-tramp-connection-property (key property &rest body)
+  "Check in Tramp for property PROPERTY, otherwise executes BODY and set."
+  `(let ((value (tramp-get-connection-property ,key ,property 'undef)))
+    (when (eq value 'undef)
+      ;; We cannot pass ,@body as parameter to
+      ;; `tramp-set-connection-property' because it mangles our debug
+      ;; messages.
+      (setq value (progn ,@body))
+      (tramp-set-connection-property ,key ,property value))
+    value))
+
+(put 'with-tramp-connection-property 'lisp-indent-function 2)
+(put 'with-tramp-connection-property 'edebug-form-spec t)
+(tramp-compat-font-lock-add-keywords
+ 'emacs-lisp-mode '("\\<with-tramp-connection-property\\>"))
 
 (defalias 'tramp-drop-volume-letter
   (if (memq system-type '(cygwin windows-nt))
@@ -2859,7 +2894,7 @@ User is always nil."
   (setq filename (expand-file-name filename))
   (let (result local-copy remote-copy)
     (with-parsed-tramp-file-name filename nil
-      (tramp-with-progress-reporter
+      (with-tramp-progress-reporter
          v 3 (format "Inserting `%s'" filename)
        (unwind-protect
            (if (not (file-exists-p filename))
@@ -2982,7 +3017,7 @@ User is always nil."
     (if (not (file-exists-p file))
        nil
       (let ((tramp-message-show-message (not nomessage)))
-       (tramp-with-progress-reporter v 0 (format "Loading %s" file)
+       (with-tramp-progress-reporter v 0 (format "Loading %s" file)
          (let ((local-copy (file-local-copy file)))
            ;; MUST-SUFFIX doesn't exist on XEmacs, so let it default to nil.
            (unwind-protect
@@ -3126,7 +3161,7 @@ beginning of local filename are not substituted."
   "Send the login name."
   (when (not (stringp tramp-current-user))
     (setq tramp-current-user
-         (with-connection-property vec "login-as"
+         (with-tramp-connection-property vec "login-as"
            (save-window-excursion
              (let ((enable-recursive-minibuffers t))
                (pop-to-buffer (tramp-get-connection-buffer vec))
@@ -3293,7 +3328,9 @@ for process communication also."
       ;; Under Windows XP, accept-process-output doesn't return
       ;; sometimes.  So we add an additional timeout.
       (with-timeout ((or timeout 1))
-       (accept-process-output proc timeout timeout-msecs)))
+       (if (featurep 'xemacs)
+           (accept-process-output proc timeout timeout-msecs)
+         (accept-process-output proc timeout timeout-msecs (and proc t)))))
     (tramp-message proc 10 "\n%s" (buffer-string))))
 
 (defun tramp-check-for-regexp (proc regexp)
@@ -3322,7 +3359,9 @@ Erase echoed commands if exists."
                     0 (min tramp-echo-mark-marker-length (1- (point-max))))
                    (tramp-compat-funcall
                     'buffer-substring-no-properties
-                    1 (min (1+ tramp-echo-mark-marker-length) (point-max))))))
+                    (point-min)
+                    (min (+ (point-min) tramp-echo-mark-marker-length)
+                         (point-max))))))
       ;; No echo to be handled, now we can look for the regexp.
       ;; Sometimes, lines are much to long, and we run into a "Stack
       ;; overflow in regexp matcher".  For example, //DIRED// lines of
@@ -3414,13 +3453,13 @@ the remote host use line-endings as defined in the variable
 (defun tramp-get-inode (vec)
   "Returns the virtual inode number.
 If it doesn't exist, generate a new one."
-  (with-file-property vec (tramp-file-name-localname vec) "inode"
+  (with-tramp-file-property vec (tramp-file-name-localname vec) "inode"
     (setq tramp-inodes (1+ tramp-inodes))))
 
 (defun tramp-get-device (vec)
   "Returns the virtual device number.
 If it doesn't exist, generate a new one."
-  (with-connection-property (tramp-get-connection-process vec) "device"
+  (with-tramp-connection-property (tramp-get-connection-process vec) "device"
     (cons -1 (setq tramp-devices (1+ tramp-devices)))))
 
 (defun tramp-equal-remote (file1 file2)
@@ -3542,7 +3581,7 @@ would yield `t'.  On the other hand, the following check results in nil:
 
 (defun tramp-get-remote-tmpdir (vec)
   "Return directory for temporary files on the remote host identified by VEC."
-  (with-connection-property vec "tmpdir"
+  (with-tramp-connection-property vec "tmpdir"
     (let ((dir (tramp-make-tramp-file-name
                (tramp-file-name-method vec)
                (tramp-file-name-user vec)
@@ -3724,6 +3763,7 @@ Invokes `password-read' if available, `read-passwd' else."
     ("oct" . 10) ("nov" . 11) ("dec" . 12))
   "Alist mapping month names to integers.")
 
+;; FIXME: Shouldn't this also look at any subseconds parts of T1 and T2?
 ;;;###tramp-autoload
 (defun tramp-time-less-p (t1 t2)
   "Say whether time value T1 is less than time value T2."
@@ -3733,6 +3773,7 @@ Invokes `password-read' if available, `read-passwd' else."
       (and (= (car t1) (car t2))
           (< (nth 1 t1) (nth 1 t2)))))
 
+;; FIXME: Shouldn't this also look at any subseconds parts of T1 and T2?
 (defun tramp-time-subtract (t1 t2)
   "Subtract two time values.
 Return the difference in the format of a time value."
@@ -3830,7 +3871,6 @@ Only works for Bourne-like shells."
 ;; * In Emacs 21, `insert-directory' shows total number of bytes used
 ;;   by the files in that directory.  Add this here.
 ;; * Avoid screen blanking when hitting `g' in dired.  (Eli Tziperman)
-;; * Make ffap.el grok Tramp filenames.  (Eli Tziperman)
 ;; * abbreviate-file-name
 ;; * Better error checking.  At least whenever we see something
 ;;   strange when doing zerop, we should kill the process and start