Add 2011 to FSF/AIST copyright years.
[bpt/emacs.git] / lisp / net / tramp-cache.el
CommitLineData
00d6fd04
MA
1;;; tramp-cache.el --- file information caching for Tramp
2
7540f029 3;; Copyright (C) 2000, 2005, 2006, 2007, 2008, 2009,
5df4f04c 4;; 2010, 2011 Free Software Foundation, Inc.
00d6fd04
MA
5
6;; Author: Daniel Pittman <daniel@inanna.danann.net>
7;; Michael Albinus <michael.albinus@gmx.de>
8;; Keywords: comm, processes
9
10;; This file is part of GNU Emacs.
11
874a927a 12;; GNU Emacs is free software: you can redistribute it and/or modify
00d6fd04 13;; it under the terms of the GNU General Public License as published by
874a927a
GM
14;; the Free Software Foundation, either version 3 of the License, or
15;; (at your option) any later version.
00d6fd04
MA
16
17;; GNU Emacs is distributed in the hope that it will be useful,
18;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20;; GNU General Public License for more details.
21
22;; You should have received a copy of the GNU General Public License
874a927a 23;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
00d6fd04
MA
24
25;;; Commentary:
26
27;; An implementation of information caching for remote files.
28
29;; Each connection, identified by a vector [method user host
30;; localname] or by a process, has a unique cache. We distinguish 3
31;; kind of caches, depending on the key:
32;;
33;; - localname is NIL. This are reusable properties. Examples:
34;; "remote-shell" identifies the POSIX shell to be called on the
35;; remote host, or "perl" is the command to be called on the remote
36;; host, when starting a Perl script. These properties are saved in
37;; the file `tramp-persistency-file-name'.
38;;
39;; - localname is a string. This are temporary properties, which are
40;; related to the file localname is referring to. Examples:
41;; "file-exists-p" is t or nile, depending on the file existence, or
42;; "file-attributes" caches the result of the function
43;; `file-attributes'.
44;;
45;; - The key is a process. This are temporary properties related to
46;; an open connection. Examples: "scripts" keeps shell script
47;; definitions already sent to the remote shell, "last-cmd-time" is
48;; the time stamp a command has been sent to the remote process.
49
50;;; Code:
51
52;; Pacify byte-compiler.
53(eval-when-compile
54 (require 'cl)
55 (autoload 'tramp-message "tramp")
56 (autoload 'tramp-tramp-file-p "tramp")
57 ;; We cannot autoload macro `with-parsed-tramp-file-name', it
58 ;; results in problems of byte-compiled code.
59 (autoload 'tramp-dissect-file-name "tramp")
60 (autoload 'tramp-file-name-method "tramp")
61 (autoload 'tramp-file-name-user "tramp")
62 (autoload 'tramp-file-name-host "tramp")
63 (autoload 'tramp-file-name-localname "tramp")
18288ba7 64 (autoload 'tramp-run-real-handler "tramp")
d5b5c94a 65 (autoload 'tramp-time-less-p "tramp")
00d6fd04
MA
66 (autoload 'time-stamp-string "time-stamp"))
67
68;;; -- Cache --
69
70(defvar tramp-cache-data (make-hash-table :test 'equal)
71 "Hash table for remote files properties.")
72
afae3a37 73(defvar tramp-cache-inhibit-cache nil
d5b5c94a
MA
74 "Inhibit cache read access, when `t'.
75`nil' means to accept cache entries unconditionally. If the
76value is a timestamp (as returned by `current-time'), cache
77entries are not used when they have been written before this
78time.")
afae3a37 79
00d6fd04
MA
80(defcustom tramp-persistency-file-name
81 (cond
82 ;; GNU Emacs.
83 ((and (boundp 'user-emacs-directory)
84 (stringp (symbol-value 'user-emacs-directory))
85 (file-directory-p (symbol-value 'user-emacs-directory)))
86 (expand-file-name "tramp" (symbol-value 'user-emacs-directory)))
87 ((and (not (featurep 'xemacs)) (file-directory-p "~/.emacs.d/"))
88 "~/.emacs.d/tramp")
89 ;; XEmacs.
90 ((and (boundp 'user-init-directory)
91 (stringp (symbol-value 'user-init-directory))
92 (file-directory-p (symbol-value 'user-init-directory)))
93 (expand-file-name "tramp" (symbol-value 'user-init-directory)))
94 ((and (featurep 'xemacs) (file-directory-p "~/.xemacs/"))
95 "~/.xemacs/tramp")
96 ;; For users without `~/.emacs.d/' or `~/.xemacs/'.
97 (t "~/.tramp"))
98 "File which keeps connection history for Tramp connections."
99 :group 'tramp
100 :type 'file)
101
7c3404ec
MA
102(defvar tramp-cache-data-changed nil
103 "Whether persistent cache data have been changed.")
104
00d6fd04
MA
105(defun tramp-get-file-property (vec file property default)
106 "Get the PROPERTY of FILE from the cache context of VEC.
107Returns DEFAULT if not set."
108 ;; Unify localname.
109 (setq vec (copy-sequence vec))
87bdd2c7 110 (aset vec 3 (tramp-run-real-handler 'directory-file-name (list file)))
00d6fd04
MA
111 (let* ((hash (or (gethash vec tramp-cache-data)
112 (puthash vec (make-hash-table :test 'equal)
113 tramp-cache-data)))
d5b5c94a
MA
114 (value (when (hash-table-p hash) (gethash property hash))))
115 (if
116 ;; We take the value only if there is any, and
117 ;; `tramp-cache-inhibit-cache' indicates that it is still
118 ;; valid. Otherwise, DEFAULT is set.
119 (and (consp value)
120 (or (null tramp-cache-inhibit-cache)
121 (and (consp tramp-cache-inhibit-cache)
122 (tramp-time-less-p
123 tramp-cache-inhibit-cache (car value)))))
124 (setq value (cdr value))
125 (setq value default))
126
127 (if (consp tramp-cache-inhibit-cache)
128 (tramp-message vec 1 "%s %s %s" file property value))
00d6fd04
MA
129 (tramp-message vec 8 "%s %s %s" file property value)
130 value))
131
132(defun tramp-set-file-property (vec file property value)
133 "Set the PROPERTY of FILE to VALUE, in the cache context of VEC.
134Returns VALUE."
135 ;; Unify localname.
136 (setq vec (copy-sequence vec))
87bdd2c7 137 (aset vec 3 (tramp-run-real-handler 'directory-file-name (list file)))
00d6fd04
MA
138 (let ((hash (or (gethash vec tramp-cache-data)
139 (puthash vec (make-hash-table :test 'equal)
140 tramp-cache-data))))
d5b5c94a
MA
141 ;; We put the timestamp there.
142 (puthash property (cons (current-time) value) hash)
00d6fd04
MA
143 (tramp-message vec 8 "%s %s %s" file property value)
144 value))
145
146(defun tramp-flush-file-property (vec file)
147 "Remove all properties of FILE in the cache context of VEC."
148 ;; Unify localname.
149 (setq vec (copy-sequence vec))
87bdd2c7 150 (aset vec 3 (tramp-run-real-handler 'directory-file-name (list file)))
00d6fd04
MA
151 (tramp-message vec 8 "%s" file)
152 (remhash vec tramp-cache-data))
153
154(defun tramp-flush-directory-property (vec directory)
155 "Remove all properties of DIRECTORY in the cache context of VEC.
156Remove also properties of all files in subdirectories."
87bdd2c7
MA
157 (let ((directory (tramp-run-real-handler
158 'directory-file-name (list directory))))
00d6fd04
MA
159 (tramp-message vec 8 "%s" directory)
160 (maphash
161 '(lambda (key value)
5ec2288f 162 (when (and (stringp (tramp-file-name-localname key))
00d6fd04
MA
163 (string-match directory (tramp-file-name-localname key)))
164 (remhash key tramp-cache-data)))
165 tramp-cache-data)))
166
00d6fd04 167;; Reverting or killing a buffer should also flush file properties.
a7580c1c
MA
168;; They could have been changed outside Tramp. In eshell, "ls" would
169;; not show proper directory contents when a file has been copied or
170;; deleted before.
00d6fd04 171(defun tramp-flush-file-function ()
06207091 172 "Flush all Tramp cache properties from `buffer-file-name'."
a7580c1c
MA
173 (let ((bfn (if (stringp (buffer-file-name))
174 (buffer-file-name)
175 default-directory)))
176 (when (tramp-tramp-file-p bfn)
00d6fd04
MA
177 (let* ((v (tramp-dissect-file-name bfn))
178 (localname (tramp-file-name-localname v)))
179 (tramp-flush-file-property v localname)))))
180
181(add-hook 'before-revert-hook 'tramp-flush-file-function)
a7580c1c 182(add-hook 'eshell-pre-command-hook 'tramp-flush-file-function)
00d6fd04
MA
183(add-hook 'kill-buffer-hook 'tramp-flush-file-function)
184(add-hook 'tramp-cache-unload-hook
185 '(lambda ()
186 (remove-hook 'before-revert-hook
187 'tramp-flush-file-function)
a7580c1c
MA
188 (remove-hook 'eshell-pre-command-hook
189 'tramp-flush-file-function)
00d6fd04
MA
190 (remove-hook 'kill-buffer-hook
191 'tramp-flush-file-function)))
192
193;;; -- Properties --
194
195(defun tramp-get-connection-property (key property default)
196 "Get the named PROPERTY for the connection.
197KEY identifies the connection, it is either a process or a vector.
198If the value is not set for the connection, returns DEFAULT."
199 ;; Unify key by removing localname from vector. Work with a copy in
200 ;; order to avoid side effects.
201 (when (vectorp key)
202 (setq key (copy-sequence key))
203 (aset key 3 nil))
204 (let* ((hash (gethash key tramp-cache-data))
205 (value (if (hash-table-p hash)
afae3a37
MA
206 (gethash property hash default)
207 default)))
00d6fd04
MA
208 (tramp-message key 7 "%s %s" property value)
209 value))
210
211(defun tramp-set-connection-property (key property value)
212 "Set the named PROPERTY of a connection to VALUE.
213KEY identifies the connection, it is either a process or a vector.
214PROPERTY is set persistent when KEY is a vector."
215 ;; Unify key by removing localname from vector. Work with a copy in
216 ;; order to avoid side effects.
217 (when (vectorp key)
218 (setq key (copy-sequence key))
219 (aset key 3 nil))
220 (let ((hash (or (gethash key tramp-cache-data)
221 (puthash key (make-hash-table :test 'equal)
222 tramp-cache-data))))
223 (puthash property value hash)
7c3404ec 224 (setq tramp-cache-data-changed t)
00d6fd04
MA
225 ;; This function is called also during initialization of
226