;;; Commentary:
-;; Tramp's main Emacs version for development is GNU Emacs 23. This
-;; package provides compatibility functions for GNU Emacs 21, GNU
-;; Emacs 22 and XEmacs 21.4+.
+;; Tramp's main Emacs version for development is GNU Emacs 24. This
+;; package provides compatibility functions for GNU Emacs 22, GNU
+;; Emacs 23 and XEmacs 21.4+.
;;; Code:
(tramp-file-name-handler
'file-remote-p file identification connected)))))
- ;; `process-file' exists since Emacs 22.
+ ;; `process-file' does not exist in XEmacs.
(unless (fboundp 'process-file)
(defalias 'process-file
(lambda (program &optional infile buffer display &rest args)
;; return the original filename if it can't expand anything. Let's
;; just hope that this doesn't break anything else.
;; It is not needed anymore since GNU Emacs 23.2.
- (unless (or (featurep 'xemacs) (featurep 'files 'remote-wildcards))
+ (unless (or (featurep 'xemacs)
+ ;; `featurep' has only one argument in XEmacs.
+ (funcall 'featurep 'files 'remote-wildcards))
(defadvice file-expand-wildcards
(around tramp-advice-file-expand-wildcards activate)
(let ((name (ad-get-arg 0)))
"`temp-directory' is defined -- using /tmp."))
(file-name-as-directory "/tmp"))))
-;; `make-temp-file' exists in Emacs only. The third parameter SUFFIX
-;; has been introduced with Emacs 22. We try it, if it fails, we fall
-;; back to `make-temp-name', creating the temporary file immediately
-;; in order to avoid a security hole.
+;; `make-temp-file' exists in Emacs only. On XEmacs, we use our own
+;; implementation with `make-temp-name', creating the temporary file
+;; immediately in order to avoid a security hole.
(defsubst tramp-compat-make-temp-file (filename &optional dir-flag)
"Create a temporary file (compat function).
Add the extension of FILENAME, if existing."
(tramp-compat-temporary-file-directory)))
(extension (file-name-extension filename t))
result)
- (condition-case nil
+ (if (fboundp 'make-temp-file)
(setq result
(funcall
(symbol-function 'make-temp-file) prefix dir-flag extension))
- (error
- ;; We use our own implementation, taken from files.el.
- (while
- (condition-case ()
- (progn
- (setq result (concat (make-temp-name prefix) extension))
- (if dir-flag
- (make-directory result)
- (write-region
- "" nil result nil 'silent nil
- ;; 7th parameter is MUSTBENEW in Emacs, and
- ;; CODING-SYSTEM in XEmacs. It is not a security
- ;; hole in XEmacs if we cannot use this parameter,
- ;; because XEmacs uses a user-specific
- ;; subdirectory with 0700 permissions.
- (when (not (featurep 'xemacs)) 'excl)))
- nil)
- (file-already-exists t))
- ;; The file was somehow created by someone else between
- ;; `make-temp-name' and `write-region', let's try again.
- nil)))
+ ;; We use our own implementation, taken from files.el.
+ (while
+ (condition-case ()
+ (progn
+ (setq result (concat (make-temp-name prefix) extension))
+ (if dir-flag
+ (make-directory result)
+ (write-region "" nil result nil 'silent))
+ nil)
+ (file-already-exists t))
+ ;; The file was somehow created by someone else between
+ ;; `make-temp-name' and `write-region', let's try again.
+ nil))
result))
-;; `most-positive-fixnum' arrived in Emacs 22. Before, and in XEmacs,
-;; it is a fixed value.
+;; `most-positive-fixnum' does not exist in XEmacs.
(defsubst tramp-compat-most-positive-fixnum ()
"Return largest positive integer value (compat function)."
(cond
((boundp 'most-positive-fixnum) (symbol-value 'most-positive-fixnum))
- ;; Default value in XEmacs and Emacs 21.
+ ;; Default value in XEmacs.
(t 134217727)))
-;; ID-FORMAT exists since Emacs 22.
+;; ID-FORMAT does not exists in XEmacs.
(defun tramp-compat-file-attributes (filename &optional id-format)
"Like `file-attributes' for Tramp files (compat function)."
(cond
(funcall
(symbol-function 'copy-directory) directory newname keep-time parents)
- ;; If default-directory is a remote directory, make sure we find
- ;; its copy-directory handler.
+ ;; If `default-directory' is a remote directory, make sure we find
+ ;; its `copy-directory' handler.
(let ((handler (or (find-file-name-handler directory 'copy-directory)
(find-file-name-handler newname 'copy-directory))))
(if handler
(if keep-time
(set-file-times newname (nth 5 (file-attributes directory))))))))
-;; `copy-tree' is a built-in function in XEmacs. In Emacs 21, it is
-;; an autoloaded function in cl-extra.el. Since Emacs 22, it is part
-;; of subr.el. There are problems when autoloading, therefore we test
-;; for `subrp' and `symbol-file'. Implementation is taken from Emacs 23.
-(defun tramp-compat-copy-tree (tree)
- "Make a copy of TREE (compat function)."
- (if (or (subrp 'copy-tree) (symbol-file 'copy-tree))
- (funcall (symbol-function 'copy-tree) tree)
- (let (result)
- (while (consp tree)
- (let ((newcar (car tree)))
- (if (consp (car tree))
- (setq newcar (tramp-compat-copy-tree (car tree))))
- (push newcar result))
- (setq tree (cdr tree)))
- (nconc (nreverse result) tree))))
-
;; RECURSIVE has been introduced with Emacs 23.2.
(defun tramp-compat-delete-directory (directory &optional recursive)
"Like `delete-directory' for Tramp files (compat function)."
- (if recursive
- (funcall (symbol-function 'delete-directory) directory recursive)
- (delete-directory directory)))
-
-;; `number-sequence' has been introduced in Emacs 22. Implementation
-;; is taken from Emacs 23.
+ (if (null recursive)
+ (delete-directory directory)
+ (condition-case nil
+ (funcall (symbol-function 'delete-directory) directory recursive)
+ ;; This Emacs version does not support the RECURSIVE flag. We
+ ;; use the implementation from Emacs 23.2.
+ (error
+ (setq directory (directory-file-name (expand-file-name directory)))
+ (if (not (file-symlink-p directory))
+ (mapc (lambda (file)
+ (if (eq t (car (file-attributes file)))
+ (tramp-compat-delete-directory file recursive)
+ (delete-file file)))
+ (directory-files
+ directory 'full "^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*")))
+ (delete-directory directory)))))
+
+;; `number-sequence' does not exist in XEmacs. Implementation is
+;; taken from Emacs 23.
(defun tramp-compat-number-sequence (from &optional to inc)
"Return a sequence of numbers from FROM to TO as a list (compat function)."
(if (or (subrp 'number-sequence) (symbol-file 'number-sequence))
;; Notes:
;; -----
;;
-;; This package only works for Emacs 21.1 and higher, and for XEmacs 21.4
+;; This package only works for Emacs 22.1 and higher, and for XEmacs 21.4
;; and higher. For XEmacs 21, you need the package `fsf-compat' for
;; the `with-timeout' macro.
;;
(when (featurep 'tramp-compat)
(unload-feature 'tramp-compat 'force))))
-(require 'format-spec) ; from Gnus 5.8, also in tar ball
+(require 'format-spec)
;; As long as password.el is not part of (X)Emacs, it shouldn't
;; be mandatory
(if (featurep 'xemacs)
(defvar tramp-completion-function-alist nil
"*Alist of methods for remote files.
-This is a list of entries of the form (NAME PAIR1 PAIR2 ...).
+This is a list of entries of the form \(NAME PAIR1 PAIR2 ...\).
Each NAME stands for a remote access method. Each PAIR is of the form
-\(FUNCTION FILE). FUNCTION is responsible to extract user names and host
+\(FUNCTION FILE\). FUNCTION is responsible to extract user names and host
names from FILE for completion. The following predefined FUNCTIONs exists:
* `tramp-parse-rhosts' for \"~/.rhosts\" like files,
(defcustom tramp-remote-process-environment
`("HISTFILE=$HOME/.tramp_history" "HISTSIZE=1" "LC_ALL=C"
- ,(concat "TERM=" tramp-terminal-type)
+ ,(format "TERM=%s" tramp-terminal-type)
"EMACS=t" ;; Deprecated.
,(format "INSIDE_EMACS=%s,tramp:%s" emacs-version tramp-version)
"CDPATH=" "HISTORY=" "MAIL=" "MAILCHECK=" "MAILPATH="
(t (error "Wrong `tramp-syntax' defined")))
"*Regular expression matching file names handled by Tramp.
This regexp should match Tramp file names but no other file names.
-\(When tramp.el is loaded, this regular expression is prepended to
+When tramp.el is loaded, this regular expression is prepended to
`file-name-handler-alist', and that is searched sequentially. Thus,
if the Tramp entry appears rather early in the `file-name-handler-alist'
and is a bit too general, then some files might be considered Tramp
files which are not really Tramp files.
Please note that the entry in `file-name-handler-alist' is made when
-this file (tramp.el) is loaded. This means that this variable must be set
+this file \(tramp.el\) is loaded. This means that this variable must be set
before loading tramp.el. Alternatively, `file-name-handler-alist' can be
updated after changing this variable.
In the Emacs normally running Tramp, evaluate the above code
\(replace \"xxx\" and \"yyy\" by the remote user and host name,
-respectively). You can do this, for example, by pasting it into
+respectively\). You can do this, for example, by pasting it into
the `*scratch*' buffer and then hitting C-j with the cursor after the
last closing parenthesis. Note that it works only if you have configured
-\"ssh\" to run without password query, see ssh-agent(1).
+\"ssh\" to run without password query, see ssh-agent\(1\).
You will see the number of bytes sent successfully to the remote host.
If that number exceeds 1000, you can stop the execution by hitting
C-g, because your Emacs is likely clean.
When it is necessary to set `tramp-chunksize', you might consider to
-use an out-of-the-band method (like \"scp\") instead of an internal one
-\(like \"ssh\"), because setting `tramp-chunksize' to non-nil decreases
+use an out-of-the-band method \(like \"scp\"\) instead of an internal one
+\(like \"ssh\"\), because setting `tramp-chunksize' to non-nil decreases
performance.
If your Emacs is buggy, the code stops and gives you an indication
(when (file-directory-p directory)
(setq directory (expand-file-name directory))
(let* ((temp
- (tramp-compat-copy-tree
+ (copy-tree
(with-parsed-tramp-file-name directory nil
(with-file-property
v localname
(tramp-shell-quote-argument localname)
(tramp-shell-quote-argument filename)
(if (symbol-value
- 'read-file-name-completion-ignore-case)
+ ;; `read-file-name-completion-ignore-case'
+ ;; is introduced with Emacs 22.1.
+ (if (boundp
+ 'read-file-name-completion-ignore-case)
+ 'read-file-name-completion-ignore-case
+ 'completion-ignore-case))
1 0)))
(format (concat
"file-name-all-completions"
result))))))))
-;; The following isn't needed for Emacs 20 but for 19.34?
(defun tramp-handle-file-name-completion
(filename directory &optional predicate)
"Like `file-name-completion' for Tramp files."
"Unknown operation `%s', must be `copy' or `rename'"
op))))
(localname1
- (if t1 (tramp-handle-file-remote-p filename 'localname) filename))
+ (if t1
+ (tramp-file-name-handler 'file-remote-p filename 'localname)
+ filename))
(localname2
- (if t2 (tramp-handle-file-remote-p newname 'localname) newname))
+ (if t2
+ (tramp-file-name-handler 'file-remote-p newname 'localname)
+ newname))
(prefix (file-remote-p (if t1 filename newname)))
cmd-result)
;; Save exit.
(condition-case nil
(if dir-flag
- (delete-directory
+ (tramp-compat-delete-directory
(expand-file-name ".." tmpfile) 'recursive)
(delete-file tmpfile))
(error))))
port (or (and port (number-to-string port)) ""))
;; Compose copy command.
- (setq spec `((?h . ,host) (?u . ,user) (?p . ,port)
- (?t . ,(tramp-get-connection-property
- (tramp-get-connection-process v) "temp-file" ""))
- (?k . ,(if keep-date " " "")))
+ (setq spec (format-spec-make
+ ?h host ?u user ?p port
+ ?t (tramp-get-connection-property
+ (tramp-get-connection-process v) "temp-file" "")
+ ?k (if keep-date " " ""))
copy-program (tramp-get-method-parameter
method 'tramp-copy-program)
copy-keep-date (tramp-get-method-parameter
(unless (eq op 'copy)
(if (file-regular-p filename)
(delete-file filename)
- (delete-directory filename 'recursive))))))
+ (tramp-compat-delete-directory filename 'recursive))))))
(defun tramp-handle-make-directory (dir &optional parents)
"Like `make-directory' for Tramp files."
"Like `find-backup-file-name' for Tramp files."
(with-parsed-tramp-file-name filename nil
;; We set both variables. It doesn't matter whether it is
- ;; Emacs or XEmacs
+ ;; Emacs or XEmacs.
(let ((backup-directory-alist
- ;; Emacs case
+ ;; Emacs case.
(when (boundp 'backup-directory-alist)
(if (symbol-value 'tramp-backup-directory-alist)
(mapcar
(symbol-value 'backup-directory-alist))))
(bkup-backup-directory-info
- ;; XEmacs case
+ ;; XEmacs case.
(when (boundp 'bkup-backup-directory-info)
(if (symbol-value 'tramp-bkup-backup-directory-info)
(mapcar
"Return file name related to OPERATION file primitive.
ARGS are the arguments OPERATION has been called with."
(cond
- ; FILE resp DIRECTORY
+ ;; FILE resp DIRECTORY.
((member operation
(list 'access-file 'byte-compiler-base-file-name 'delete-directory
'delete-file 'diff-latest-backup-file 'directory-file-name
'load 'make-directory 'make-directory-internal
'set-file-modes 'substitute-in-file-name
'unhandled-file-name-directory 'vc-registered
- ; Emacs 22 only
+ ;; Emacs 22+ only.
'set-file-times
- ; XEmacs only
+ ;; XEmacs only.
'abbreviate-file-name 'create-file-buffer
'dired-file-modtime 'dired-make-compressed-filename
'dired-recursive-delete-directory 'dired-set-file-modtime
(if (file-name-absolute-p (nth 0 args))
(nth 0 args)
(expand-file-name (nth 0 args))))
- ; FILE DIRECTORY resp FILE1 FILE2
+ ;; FILE DIRECTORY resp FILE1 FILE2.
((member operation
(list 'add-name-to-file 'copy-file 'expand-file-name
'file-name-all-completions 'file-name-completion
'file-newer-than-file-p 'make-symbolic-link 'rename-file
- ; Emacs 23 only
+ ;; Emacs 23+ only.
'copy-directory
- ; XEmacs only
+ ;; XEmacs only.
'dired-make-relative-symlink
'vm-imap-move-mail 'vm-pop-move-mail 'vm-spool-move-mail))
(save-match-data
((string-match tramp-file-name-regexp (nth 0 args)) (nth 0 args))
((string-match tramp-file-name-regexp (nth 1 args)) (nth 1 args))
(t (buffer-file-name (current-buffer))))))
- ; START END FILE
+ ;; START END FILE.
((eq operation 'write-region)
(nth 2 args))
- ; BUF
+ ;; BUFFER.
((member operation
(list 'set-visited-file-modtime 'verify-visited-file-modtime
- ; since Emacs 22 only
+ ;; Emacs 22+ only.
'make-auto-save-file-name
- ; XEmacs only
+ ;; XEmacs only.
'backup-buffer))
(buffer-file-name
(if (bufferp (nth 0 args)) (nth 0 args) (current-buffer))))
- ; COMMAND
+ ;; COMMAND.
((member operation
- (list ; not in Emacs 23
+ (list ;; not in Emacs 23+.
'dired-call-process
- ; Emacs only
+ ;; Emacs only.
'shell-command
- ; since Emacs 22 only
+ ;; Emacs 22+ only.
'process-file
- ; since Emacs 23 only
+ ;; Emacs 23+ only.
'start-file-process
- ; XEmacs only
+ ;; XEmacs only.
'dired-print-file 'dired-shell-call-process
- ; nowhere yet
+ ;; nowhere yet.
'executable-find 'start-process 'call-process))
default-directory)
- ; unknown file primitive
+ ;; Unknown file primitive.
(t (error "unknown file I/O primitive: %s" operation))))
(defun tramp-find-foreign-file-name-handler (filename)
"Return foreign file name handler if exists."
- (when (and (stringp filename) (tramp-tramp-file-p filename))
+ (when (tramp-tramp-file-p filename)
(let ((v (tramp-dissect-file-name filename t))
(handler tramp-foreign-file-name-handler-alist)
elt res)
(format "*debug tramp/%s %s@%s*" method user host)
(format "*debug tramp/%s %s*" method host))))
+(defconst tramp-debug-outline-regexp
+ "[0-9]+:[0-9]+:[0-9]+\\.[0-9]+ [a-z0-9-]+ (\\([0-9]+\\)) #")
+
(defun tramp-get-debug-buffer (vec)
"Get the debug buffer for VEC."
(with-current-buffer
(get-buffer-create (tramp-debug-buffer-name vec))
(when (bobp)
(setq buffer-undo-list t)
- ;; Activate outline-mode. This runs `text-mode-hook' and
+ ;; Activate `outline-mode'. This runs `text-mode-hook' and
;; `outline-mode-hook'. We must prevent that local processes
- ;; die. Yes: I've seen `flyspell-mode', which starts "ispell"
- ;; ...
- (let ((default-directory (tramp-compat-temporary-file-directory)))
+ ;; die. Yes: I've seen `flyspell-mode', which starts "ispell".
+ ;; Furthermore, `outline-regexp' must have the correct value
+ ;; already, because it is used by `font-lock-compile-keywords'.
+ (let ((default-directory (tramp-compat-temporary-file-directory))
+ (outline-regexp tramp-debug-outline-regexp))
(outline-mode))
- (set (make-local-variable 'outline-regexp)
- "[0-9]+:[0-9]+:[0-9]+\\.[0-9]+ [a-z0-9-]+ (\\([0-9]+\\)) #")
-; (set (make-local-variable 'outline-regexp)
-; "[a-z.-]+:[0-9]+: [a-z0-9-]+ (\\([0-9]+\\)) #")
+ (set (make-local-variable 'outline-regexp) tramp-debug-outline-regexp)
(set (make-local-variable 'outline-level) 'tramp-outline-level))
(current-buffer)))
(setq result (concat "\\" progname))))
(unless result
(when ignore-tilde
- ;; Remove all ~/foo directories from dirlist. In Emacs 20,
+ ;; Remove all ~/foo directories from dirlist. In XEmacs,
;; `remove' is in CL, and we want to avoid CL dependencies.
(let (newdl d)
(while dirlist
;; Discard echo from remote output.
(tramp-set-connection-property proc "check-remote-echo" nil)
(tramp-message proc 5 "echo-mark found")
- (forward-line)
+ (forward-line 1)
(delete-region begin (point))
(goto-char (point-min)))))
"List of local coding commands for inline transfer.
Each item is a list that looks like this:
-\(FORMAT ENCODING DECODING)
+\(FORMAT ENCODING DECODING\)
FORMAT is symbol describing the encoding/decoding format. It can be
`b64' for base64 encoding, `uu' for uu encoding, or `pack' for simple packing.
"List of remote coding commands for inline transfer.
Each item is a list that looks like this:
-\(FORMAT ENCODING DECODING)
+\(FORMAT ENCODING DECODING\)
FORMAT is symbol describing the encoding/decoding format. It can be
`b64' for base64 encoding, `uu' for uu encoding, or `pack' for simple packing.
(setq proxy
(format-spec
proxy
- `((?u . ,(or (tramp-file-name-user (car target-alist)) ""))
- (?h . ,(or (tramp-file-name-host (car target-alist)) "")))))
+ (format-spec-make
+ ?u (or (tramp-file-name-user (car target-alist)) "")
+ ?h (or (tramp-file-name-host (car target-alist)) ""))))
(with-parsed-tramp-file-name proxy l
;; Add the hop.
(add-to-list 'target-alist l)
l-host (or l-host "")
l-user (or l-user "")
l-port (or l-port "")
- spec `((?h . ,l-host) (?u . ,l-user) (?p . ,l-port)
- (?t . ,tmpfile))
+ spec (format-spec-make ?h l-host ?u l-user ?p l-port ?t tmpfile)
command
(concat
;; We do not want to see the trailing local prompt in
(tramp-get-connection-process vec)
vec)
"remote-path"
- (let* ((remote-path (tramp-compat-copy-tree tramp-remote-path))
+ (let* ((remote-path (copy-tree tramp-remote-path))
(elt1 (memq 'tramp-default-remote-path remote-path))
(elt2 (memq 'tramp-own-remote-path remote-path))
(default-remote-path
(defadvice make-auto-save-file-name
(around tramp-advice-make-auto-save-file-name () activate)
"Invoke `tramp-handle-make-auto-save-file-name' for Tramp files."
- (if (and (buffer-file-name) (tramp-tramp-file-p (buffer-file-name)))
+ (if (tramp-tramp-file-p (buffer-file-name))
;; We cannot call `tramp-handle-make-auto-save-file-name'
;; directly, because this would bypass the locking mechanism.
(setq ad-return-value
'around 'tramp-advice-make-auto-save-file-name)
(ad-activate 'make-auto-save-file-name))))
-;; In Emacs < 22 and XEmacs < 21.5 autosaved remote files have
-;; permission 0666 minus umask. This is a security threat.
+;; In XEmacs < 21.5, autosaved remote files have permission 0666 minus
+;; umask. This is a security threat.
(defun tramp-set-auto-save-file-modes ()
"Set permissions of autosaved remote files to the original permissions."
(let ((bfn (buffer-file-name)))
- (when (and (stringp bfn)
- (tramp-tramp-file-p bfn)
+ (when (and (tramp-tramp-file-p bfn)
(buffer-modified-p)
(stringp buffer-auto-save-file-name)
(not (equal bfn buffer-auto-save-file-name)))
(set-file-modes buffer-auto-save-file-name
(or (file-modes bfn) (tramp-octal-to-decimal "0600"))))))
-(unless (or (> emacs-major-version 21)
- (and (featurep 'xemacs)
- (= emacs-major-version 21)
- (> emacs-minor-version 4)))
+(unless (and (featurep 'xemacs)
+ (= emacs-major-version 21)
+ (> emacs-minor-version 4))
(add-hook 'auto-save-hook 'tramp-set-auto-save-file-modes)
(add-hook 'tramp-unload-hook
(lambda ()
;; expects only English messages? (Juri Linkov)
;; * Make shadowfile.el grok Tramp filenames. (Bug#4526, Bug#4846)
;; * Do not handle files with drive letter as remote. (Bug#5447)
-;; * Load Tramp subpackages only when needed. (Bug#1529, Bug#5448)
+;; * Load Tramp subpackages only when needed. (Bug#1529, Bug#5448, Bug#5705)
;; * Try telnet+curl as new method. It might be useful for busybox,
;; without built-in uuencode/uudecode.
;; * Let `shell-dynamic-complete-*' and `comint-dynamic-complete' work