diff options
| author | Dave Love | 2000-04-09 17:18:48 +0000 |
|---|---|---|
| committer | Dave Love | 2000-04-09 17:18:48 +0000 |
| commit | 86724078eac458d89e6b1acb98fda23d9c0ef40a (patch) | |
| tree | aa3a854fc955099450fb47bbf390842e85e98e79 | |
| parent | be0dbdab007cf09a2cac30c89ad4d530b08abeae (diff) | |
| download | emacs-86724078eac458d89e6b1acb98fda23d9c0ef40a.tar.gz emacs-86724078eac458d89e6b1acb98fda23d9c0ef40a.zip | |
(backup-enable-predicate): Use temporary-file-directory,
small-temporary-file-directory.
(make-backup-file-name-function, backup-directory-alist): New
variables.
(make-backup-file-name-1): New function.
(make-backup-file-name): Use it.
(find-backup-file-name): Likewise. Use format for clarity, not concat.
(file-newest-backup): Use make-backup-file-name.
| -rw-r--r-- | lisp/files.el | 177 |
1 files changed, 133 insertions, 44 deletions
diff --git a/lisp/files.el b/lisp/files.el index 9de7c0ba8ea..f3af7b9e511 100644 --- a/lisp/files.el +++ b/lisp/files.el | |||
| @@ -135,10 +135,20 @@ This variable is relevant only if `backup-by-copying' and | |||
| 135 | 135 | ||
| 136 | (defvar backup-enable-predicate | 136 | (defvar backup-enable-predicate |
| 137 | '(lambda (name) | 137 | '(lambda (name) |
| 138 | (or (< (length name) 5) | 138 | (and (let ((comp (compare-strings temporary-file-directory 0 nil |
| 139 | (not (string-equal "/tmp/" (substring name 0 5))))) | 139 | name 0 nil))) |
| 140 | (and (not (eq comp t)) | ||
| 141 | (< comp -1))) | ||
| 142 | (if small-temporary-file-directory | ||
| 143 | (let ((comp (compare-strings small-temporary-file-directory 0 nil | ||
| 144 | name 0 nil))) | ||
| 145 | (and (not (eq comp t)) | ||
| 146 | (< comp -1))) | ||
| 147 | t))) | ||
| 140 | "Predicate that looks at a file name and decides whether to make backups. | 148 | "Predicate that looks at a file name and decides whether to make backups. |
| 141 | Called with an absolute file name as argument, it returns t to enable backup.") | 149 | Called with an absolute file name as argument, it returns t to enable backup. |
| 150 | The default version checks for files in `temporary-file-directory' or | ||
| 151 | `small-temporary-file-directory'.") | ||
| 142 | 152 | ||
| 143 | (defcustom buffer-offer-save nil | 153 | (defcustom buffer-offer-save nil |
| 144 | "*Non-nil in a buffer means always offer to save buffer on exit. | 154 | "*Non-nil in a buffer means always offer to save buffer on exit. |
| @@ -724,7 +734,7 @@ expand wildcards (if any) and visit multiple files." | |||
| 724 | 734 | ||
| 725 | (defun find-file-read-only (filename &optional wildcards) | 735 | (defun find-file-read-only (filename &optional wildcards) |
| 726 | "Edit file FILENAME but don't allow changes. | 736 | "Edit file FILENAME but don't allow changes. |
| 727 | Like \\[find-file] but marks buffer as read-only. | 737 | Like `find-file' but marks buffer as read-only. |
| 728 | Use \\[toggle-read-only] to permit editing." | 738 | Use \\[toggle-read-only] to permit editing." |
| 729 | (interactive "fFind file read-only: \np") | 739 | (interactive "fFind file read-only: \np") |
| 730 | (find-file filename wildcards) | 740 | (find-file filename wildcards) |
| @@ -1571,10 +1581,9 @@ and we don't even do that unless it would come from the file name." | |||
| 1571 | (if (string-match (car (car alist)) name) | 1581 | (if (string-match (car (car alist)) name) |
| 1572 | (if (and (consp (cdr (car alist))) | 1582 | (if (and (consp (cdr (car alist))) |
| 1573 | (nth 2 (car alist))) | 1583 | (nth 2 (car alist))) |
| 1574 | (progn | 1584 | (setq mode (car (cdr (car alist))) |
| 1575 | (setq mode (car (cdr (car alist))) | 1585 | name (substring name 0 (match-beginning 0)) |
| 1576 | name (substring name 0 (match-beginning 0)) | 1586 | keep-going t) |
| 1577 | keep-going t)) | ||
| 1578 | (setq mode (cdr (car alist)) | 1587 | (setq mode (cdr (car alist)) |
| 1579 | keep-going nil))) | 1588 | keep-going nil))) |
| 1580 | (setq alist (cdr alist)))) | 1589 | (setq alist (cdr alist)))) |
| @@ -1593,9 +1602,9 @@ and we don't even do that unless it would come from the file name." | |||
| 1593 | (let ((interpreter | 1602 | (let ((interpreter |
| 1594 | (save-excursion | 1603 | (save-excursion |
| 1595 | (goto-char (point-min)) | 1604 | (goto-char (point-min)) |
| 1596 | (if (looking-at "#![ \t]?\\([^ \t\n]*/bin/env[ \t]\\)?\\([^ \t\n]+\\)") | 1605 | (if (looking-at "#![ \t]?\\([^ \t\n]*\ |
| 1597 | (buffer-substring (match-beginning 2) | 1606 | /bin/env[ \t]\\)?\\([^ \t\n]+\\)") |
| 1598 | (match-end 2)) | 1607 | (match-string 2) |
| 1599 | ""))) | 1608 | ""))) |
| 1600 | elt) | 1609 | elt) |
| 1601 | ;; Map interpreter name to a mode. | 1610 | ;; Map interpreter name to a mode. |
| @@ -2173,19 +2182,94 @@ the value is \"\"." | |||
| 2173 | (if period | 2182 | (if period |
| 2174 | ""))))) | 2183 | ""))))) |
| 2175 | 2184 | ||
| 2185 | (defcustom make-backup-file-name-function nil | ||
| 2186 | "A function to use instead of the default `make-backup-file-name'. | ||
| 2187 | A value of nil gives the default `make-backup-file-name' behaviour. | ||
| 2188 | |||
| 2189 | This could be buffer-local to do something special for for specific | ||
| 2190 | files. If you define it, you may need to change `backup-file-name-p' | ||
| 2191 | and `file-name-sans-versions' too. | ||
| 2192 | |||
| 2193 | See also `backup-directory-alist'." | ||
| 2194 | :group 'backup | ||
| 2195 | :type '(choice (const :tag "Default" nil) | ||
| 2196 | (function :tag "Your function"))) | ||
| 2197 | |||
| 2198 | (defcustom backup-directory-alist nil | ||
| 2199 | "Alist of filename patterns and backup directory names. | ||
| 2200 | Each element looks like (REGEXP . DIRECTORY). Backups of files with | ||
| 2201 | names matching REGEXP will be made in DIRECTORY. DIRECTORY may be | ||
| 2202 | relative or absolute. If it is absolute, so that all matching files | ||
| 2203 | are backed up into the same directory, the file names in this | ||
| 2204 | directory will be the full name of the file backed up with all | ||
| 2205 | directory separators changed to `|' to prevent clashes. This will not | ||
| 2206 | work correctly if your filesystem truncates the resulting name. | ||
| 2207 | |||
| 2208 | For the common case of all backups going into one directory, the alist | ||
| 2209 | should contain a single element pairing \".\" with the appropriate | ||
| 2210 | directory name. | ||
| 2211 | |||
| 2212 | If this variable is nil, or it fails to match a filename, the backup | ||
| 2213 | is made in the original file's directory. | ||
| 2214 | |||
| 2215 | On MS-DOS filesystems without long names this variable is always | ||
| 2216 | ignored." | ||
| 2217 | :group 'backup | ||
| 2218 | :type '(repeat (cons (regexp :tag "Regexp macthing filename") | ||
| 2219 | (directory :tag "Backup directory name")))) | ||
| 2220 | |||
| 2176 | (defun make-backup-file-name (file) | 2221 | (defun make-backup-file-name (file) |
| 2177 | "Create the non-numeric backup file name for FILE. | 2222 | "Create the non-numeric backup file name for FILE. |
| 2178 | This is a separate function so you can redefine it for customization." | 2223 | Normally this will just be the file's name with `~' appended. |
| 2179 | (if (and (eq system-type 'ms-dos) | 2224 | Customization hooks are provided as follows. |
| 2180 | (not (msdos-long-file-names))) | 2225 | |
| 2181 | (let ((fn (file-name-nondirectory file))) | 2226 | If the variable `make-backup-file-name-function' is non-nil, its value |
| 2182 | (concat (file-name-directory file) | 2227 | should be a function which will be called with FILE as its argument; |
| 2183 | (or | 2228 | the resulting name is used. |
| 2184 | (and (string-match "\\`[^.]+\\'" fn) | 2229 | |
| 2185 | (concat (match-string 0 fn) ".~")) | 2230 | Otherwise a match for FILE is sought in `backup-directory-alist'; see |
| 2186 | (and (string-match "\\`[^.]+\\.\\(..?\\)?" fn) | 2231 | the documentation of that variable. If the directory for the backup |
| 2187 | (concat (match-string 0 fn) "~"))))) | 2232 | doesn't exist, it is created." |
| 2188 | (concat file "~"))) | 2233 | (if make-backup-file-name-function |
| 2234 | (funcall make-backup-file-name-function file) | ||
| 2235 | (if (and (eq system-type 'ms-dos) | ||
| 2236 | (not (msdos-long-file-names))) | ||
| 2237 | (let ((fn (file-name-nondirectory file))) | ||
| 2238 | (concat (file-name-directory file) | ||
| 2239 | (or (and (string-match "\\`[^.]+\\'" fn) | ||
| 2240 | (concat (match-string 0 fn) ".~")) | ||
| 2241 | (and (string-match "\\`[^.]+\\.\\(..?\\)?" fn) | ||
| 2242 | (concat (match-string 0 fn) "~"))))) | ||
| 2243 | (concat (make-backup-file-name-1 file) "~")))) | ||
| 2244 | |||
| 2245 | (defun make-backup-file-name-1 (file) | ||
| 2246 | "Subroutine of `make-backup-file-name' and `find-backup-file-name'." | ||
| 2247 | (let ((alist backup-directory-alist) | ||
| 2248 | elt backup-directory) | ||
| 2249 | (while alist | ||
| 2250 | (setq elt (pop alist)) | ||
| 2251 | (if (string-match (car elt) file) | ||
| 2252 | (setq backup-directory (cdr elt) | ||
| 2253 | alist nil))) | ||
| 2254 | (if (null backup-directory) | ||
| 2255 | file | ||
| 2256 | (unless (file-exists-p backup-directory) | ||
| 2257 | (condition-case nil | ||
| 2258 | (make-directory backup-directory 'parents) | ||
| 2259 | (file-error file))) | ||
| 2260 | (if (file-name-absolute-p backup-directory) | ||
| 2261 | ;; Make the name unique by substituting directory | ||
| 2262 | ;; separators. It may not really be worth bothering about | ||
| 2263 | ;; doubling `|'s in the original name... | ||
| 2264 | (expand-file-name | ||
| 2265 | (subst-char-in-string | ||
| 2266 | directory-sep-char ?| | ||
| 2267 | (replace-regexp-in-string "|" "||" file)) | ||
| 2268 | backup-directory) | ||
| 2269 | (expand-file-name (file-name-nondirectory file) | ||
| 2270 | (file-name-as-directory | ||
| 2271 | (expand-file-name backup-directory | ||
| 2272 | (file-name-directory file)))))))) | ||
| 2189 | 2273 | ||
| 2190 | (defun backup-file-name-p (file) | 2274 | (defun backup-file-name-p (file) |
| 2191 | "Return non-nil if FILE is a backup file name (numeric or not). | 2275 | "Return non-nil if FILE is a backup file name (numeric or not). |
| @@ -2212,45 +2296,47 @@ the index in the name where the version number begins." | |||
| 2212 | (defun find-backup-file-name (fn) | 2296 | (defun find-backup-file-name (fn) |
| 2213 | "Find a file name for a backup file FN, and suggestions for deletions. | 2297 | "Find a file name for a backup file FN, and suggestions for deletions. |
| 2214 | Value is a list whose car is the name for the backup file | 2298 | Value is a list whose car is the name for the backup file |
| 2215 | and whose cdr is a list of old versions to consider deleting now. | 2299 | and whose cdr is a list of old versions to consider deleting now. |
| 2216 | If the value is nil, don't make a backup." | 2300 | If the value is nil, don't make a backup. |
| 2301 | Uses `backup-directory-alist' in the same way as does | ||
| 2302 | `make-backup-file-name'." | ||
| 2217 | (let ((handler (find-file-name-handler fn 'find-backup-file-name))) | 2303 | (let ((handler (find-file-name-handler fn 'find-backup-file-name))) |
| 2218 | ;; Run a handler for this function so that ange-ftp can refuse to do it. | 2304 | ;; Run a handler for this function so that ange-ftp can refuse to do it. |
| 2219 | (if handler | 2305 | (if handler |
| 2220 | (funcall handler 'find-backup-file-name fn) | 2306 | (funcall handler 'find-backup-file-name fn) |
| 2221 | (if (eq version-control 'never) | 2307 | (if (eq version-control 'never) |
| 2222 | (list (make-backup-file-name fn)) | 2308 | (list (make-backup-file-name fn)) |
| 2223 | (let* ((base-versions (concat (file-name-nondirectory fn) ".~")) | 2309 | (let* ((basic-name (make-backup-file-name-1 fn)) |
| 2310 | (base-versions (concat (file-name-nondirectory basic-name) | ||
| 2311 | ".~")) | ||
| 2224 | (backup-extract-version-start (length base-versions)) | 2312 | (backup-extract-version-start (length base-versions)) |
| 2225 | possibilities | ||
| 2226 | (versions nil) | ||
| 2227 | (high-water-mark 0) | 2313 | (high-water-mark 0) |
| 2228 | (deserve-versions-p nil) | 2314 | (number-to-delete 0) |
| 2229 | (number-to-delete 0)) | 2315 | possibilities deserve-versions-p versions) |
| 2230 | (condition-case () | 2316 | (condition-case () |
| 2231 | (setq possibilities (file-name-all-completions | 2317 | (setq possibilities (file-name-all-completions |
| 2232 | base-versions | 2318 | base-versions |
| 2233 | (file-name-directory fn)) | 2319 | (file-name-directory basic-name)) |
| 2234 | versions (sort (mapcar | 2320 | versions (sort (mapcar #'backup-extract-version |
| 2235 | (function backup-extract-version) | 2321 | possibilities) |
| 2236 | possibilities) | 2322 | #'<) |
| 2237 | '<) | ||
| 2238 | high-water-mark (apply 'max 0 versions) | 2323 | high-water-mark (apply 'max 0 versions) |
| 2239 | deserve-versions-p (or version-control | 2324 | deserve-versions-p (or version-control |
| 2240 | (> high-water-mark 0)) | 2325 | (> high-water-mark 0)) |
| 2241 | number-to-delete (- (length versions) | 2326 | number-to-delete (- (length versions) |
| 2242 | kept-old-versions kept-new-versions -1)) | 2327 | kept-old-versions |
| 2243 | (file-error | 2328 | kept-new-versions |
| 2244 | (setq possibilities nil))) | 2329 | -1)) |
| 2330 | (file-error (setq possibilities nil))) | ||
| 2245 | (if (not deserve-versions-p) | 2331 | (if (not deserve-versions-p) |
| 2246 | (list (make-backup-file-name fn)) | 2332 | (list (concat basic-name "~")) |
| 2247 | (cons (concat fn ".~" (int-to-string (1+ high-water-mark)) "~") | 2333 | (cons (format "%s.~%d~" basic-name (1+ high-water-mark)) |
| 2248 | (if (and (> number-to-delete 0) | 2334 | (if (and (> number-to-delete 0) |
| 2249 | ;; Delete nothing if there is overflow | 2335 | ;; Delete nothing if there is overflow |
| 2250 | ;; in the number of versions to keep. | 2336 | ;; in the number of versions to keep. |
| 2251 | (>= (+ kept-new-versions kept-old-versions -1) 0)) | 2337 | (>= (+ kept-new-versions kept-old-versions -1) 0)) |
| 2252 | (mapcar (function (lambda (n) | 2338 | (mapcar (lambda (n) |
| 2253 | (concat fn ".~" (int-to-string n) "~"))) | 2339 | (format "%s.~%d~" basic-name n)) |
| 2254 | (let ((v (nthcdr kept-old-versions versions))) | 2340 | (let ((v (nthcdr kept-old-versions versions))) |
| 2255 | (rplacd (nthcdr (1- number-to-delete) v) ()) | 2341 | (rplacd (nthcdr (1- number-to-delete) v) ()) |
| 2256 | v)))))))))) | 2342 | v)))))))))) |
| @@ -2651,15 +2737,18 @@ saying what text to write." | |||
| 2651 | 2737 | ||
| 2652 | (defun file-newest-backup (filename) | 2738 | (defun file-newest-backup (filename) |
| 2653 | "Return most recent backup file for FILENAME or nil if no backups exist." | 2739 | "Return most recent backup file for FILENAME or nil if no backups exist." |
| 2654 | (let* ((filename (expand-file-name filename)) | 2740 | ;; `make-backup-file-name' will get us the right directory for |
| 2741 | ;; ordinary or numeric backups. It might create a directory for | ||
| 2742 | ;; backups as a side-effect, according to `backup-directory-alist'. | ||
| 2743 | (let* ((filename (file-name-sans-versions | ||
| 2744 | (make-backup-file-name filename))) | ||
| 2655 | (file (file-name-nondirectory filename)) | 2745 | (file (file-name-nondirectory filename)) |
| 2656 | (dir (file-name-directory filename)) | 2746 | (dir (file-name-directory filename)) |
| 2657 | (comp (file-name-all-completions file dir)) | 2747 | (comp (file-name-all-completions file dir)) |
| 2658 | (newest nil) | 2748 | (newest nil) |
| 2659 | tem) | 2749 | tem) |
| 2660 | (while comp | 2750 | (while comp |
| 2661 | (setq tem (car comp) | 2751 | (setq tem (pop comp)) |
| 2662 | comp (cdr comp)) | ||
| 2663 | (cond ((and (backup-file-name-p tem) | 2752 | (cond ((and (backup-file-name-p tem) |
| 2664 | (string= (file-name-sans-versions tem) file)) | 2753 | (string= (file-name-sans-versions tem) file)) |
| 2665 | (setq tem (concat dir tem)) | 2754 | (setq tem (concat dir tem)) |