aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lisp/files.el5
-rw-r--r--lisp/net/ange-ftp.el118
-rw-r--r--lisp/net/tramp-compat.el27
-rw-r--r--lisp/net/tramp-gvfs.el2
-rw-r--r--lisp/net/tramp-sh.el3
-rw-r--r--lisp/net/tramp.el6
-rw-r--r--test/lisp/net/tramp-tests.el23
7 files changed, 118 insertions, 66 deletions
diff --git a/lisp/files.el b/lisp/files.el
index e55552a2d9a..deb878cf418 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -5867,10 +5867,7 @@ RECURSIVE if DIRECTORY is nonempty."
5867 ;; case, where the operation fails in delete-directory-internal. 5867 ;; case, where the operation fails in delete-directory-internal.
5868 ;; As `move-file-to-trash' trashes directories (empty or 5868 ;; As `move-file-to-trash' trashes directories (empty or
5869 ;; otherwise) as a unit, we do not need to recurse here. 5869 ;; otherwise) as a unit, we do not need to recurse here.
5870 (if (and (not recursive) 5870 (if (not (or recursive (directory-empty-p directory)))
5871 ;; Check if directory is empty apart from "." and "..".
5872 (directory-files
5873 directory 'full directory-files-no-dot-files-regexp))
5874 (error "Directory is not empty, not moving to trash") 5871 (error "Directory is not empty, not moving to trash")
5875 (move-file-to-trash directory))) 5872 (move-file-to-trash directory)))
5876 ;; Otherwise, call ourselves recursively if needed. 5873 ;; Otherwise, call ourselves recursively if needed.
diff --git a/lisp/net/ange-ftp.el b/lisp/net/ange-ftp.el
index 15322219eff..e0c162df577 100644
--- a/lisp/net/ange-ftp.el
+++ b/lisp/net/ange-ftp.el
@@ -3536,20 +3536,22 @@ system TYPE.")
3536 (setq file (expand-file-name file)) 3536 (setq file (expand-file-name file))
3537 (let ((parsed (ange-ftp-ftp-name file))) 3537 (let ((parsed (ange-ftp-ftp-name file)))
3538 (if parsed 3538 (if parsed
3539 (let* ((host (nth 0 parsed)) 3539 (if (and delete-by-moving-to-trash trash)
3540 (user (nth 1 parsed)) 3540 (move-file-to-trash file)
3541 (name (ange-ftp-quote-string (nth 2 parsed))) 3541 (let* ((host (nth 0 parsed))
3542 (abbr (ange-ftp-abbreviate-filename file)) 3542 (user (nth 1 parsed))
3543 (result (ange-ftp-send-cmd host user 3543 (name (ange-ftp-quote-string (nth 2 parsed)))
3544 (list 'delete name) 3544 (abbr (ange-ftp-abbreviate-filename file))
3545 (format "Deleting %s" abbr)))) 3545 (result (ange-ftp-send-cmd host user
3546 (or (car result) 3546 (list 'delete name)
3547 (signal 'ftp-error 3547 (format "Deleting %s" abbr))))
3548 (list 3548 (or (car result)
3549 "Removing old name" 3549 (signal 'ftp-error
3550 (format "FTP Error: \"%s\"" (cdr result)) 3550 (list
3551 file))) 3551 "Removing old name"
3552 (ange-ftp-delete-file-entry file)) 3552 (format "FTP Error: \"%s\"" (cdr result))
3553 file)))
3554 (ange-ftp-delete-file-entry file)))
3553 (ange-ftp-real-delete-file file trash)))) 3555 (ange-ftp-real-delete-file file trash))))
3554 3556
3555(defun ange-ftp-file-modtime (file) 3557(defun ange-ftp-file-modtime (file)
@@ -4163,45 +4165,55 @@ directory, so that Emacs will know its current contents."
4163 4165
4164(defun ange-ftp-delete-directory (dir &optional recursive trash) 4166(defun ange-ftp-delete-directory (dir &optional recursive trash)
4165 (if (file-directory-p dir) 4167 (if (file-directory-p dir)
4166 (let ((parsed (ange-ftp-ftp-name dir))) 4168 ;; Trashing directories does not work yet, because
4167 (if recursive 4169 ;; `rename-file', called in `move-file-to-trash', does not
4168 (mapc 4170 ;; handle directories.
4169 (lambda (file) 4171 (if nil ; (and delete-by-moving-to-trash trash)
4170 (if (file-directory-p file) 4172 ;; Move non-empty dir to trash only if recursive deletion was
4171 (ange-ftp-delete-directory file recursive trash) 4173 ;; requested.
4172 (delete-file file trash))) 4174 (if (not (or recursive (directory-empty-p dir)))
4173 (directory-files dir 'full directory-files-no-dot-files-regexp))) 4175 (signal 'ftp-error
4174 (if parsed 4176 (list "Directory is not empty, not moving to trash"))
4175 (let* ((host (nth 0 parsed)) 4177 (move-file-to-trash dir))
4176 (user (nth 1 parsed)) 4178 (let ((parsed (ange-ftp-ftp-name dir)))
4177 ;; Some ftp's on unix machines (at least on Suns) 4179 (if recursive
4178 ;; insist that rmdir take a filename, and not a 4180 (mapc
4179 ;; directory-name name as an arg. Argh!! This is a bug. 4181 (lambda (file)
4180 ;; Non-unix machines will probably always insist 4182 (if (file-directory-p file)
4181 ;; that rmdir takes a directory-name as an arg 4183 (ange-ftp-delete-directory file recursive)
4182 ;; (as the ftp man page says it should). 4184 (delete-file file)))
4183 (name (ange-ftp-quote-string 4185 (directory-files dir 'full directory-files-no-dot-files-regexp)))
4184 (if (eq (ange-ftp-host-type host) 'unix) 4186 (if parsed
4185 (ange-ftp-real-directory-file-name 4187 (let* ((host (nth 0 parsed))
4186 (nth 2 parsed)) 4188 (user (nth 1 parsed))
4187 (ange-ftp-real-file-name-as-directory 4189 ;; Some ftp's on unix machines (at least on Suns)
4188 (nth 2 parsed))))) 4190 ;; insist that rmdir take a filename, and not a
4189 (abbr (ange-ftp-abbreviate-filename dir)) 4191 ;; directory-name name as an arg. Argh!! This is a bug.
4190 (result 4192 ;; Non-unix machines will probably always insist
4191 (progn 4193 ;; that rmdir takes a directory-name as an arg
4192 ;; CWD must not in this directory. 4194 ;; (as the ftp man page says it should).
4193 (ange-ftp-cd host user "/" 'noerror) 4195 (name (ange-ftp-quote-string
4194 (ange-ftp-send-cmd host user 4196 (if (eq (ange-ftp-host-type host) 'unix)
4195 (list 'rmdir name) 4197 (ange-ftp-real-directory-file-name
4196 (format "Removing directory %s" 4198 (nth 2 parsed))
4197 abbr))))) 4199 (ange-ftp-real-file-name-as-directory
4198 (or (car result) 4200 (nth 2 parsed)))))
4199 (ange-ftp-error host user 4201 (abbr (ange-ftp-abbreviate-filename dir))
4200 (format "Could not remove directory %s: %s" 4202 (result
4201 dir 4203 (progn
4202 (cdr result)))) 4204 ;; CWD must not in this directory.
4203 (ange-ftp-delete-file-entry dir t)) 4205 (ange-ftp-cd host user "/" 'noerror)
4204 (ange-ftp-real-delete-directory dir recursive trash))) 4206 (ange-ftp-send-cmd host user
4207 (list 'rmdir name)
4208 (format "Removing directory %s"
4209 abbr)))))
4210 (or (car result)
4211 (ange-ftp-error host user
4212 (format "Could not remove directory %s: %s"
4213 dir
4214 (cdr result))))
4215 (ange-ftp-delete-file-entry dir t))
4216 (ange-ftp-real-delete-directory dir recursive trash))))
4205 (error "Not a directory: %s" dir))) 4217 (error "Not a directory: %s" dir)))
4206 4218
4207;; Make a local copy of FILE and return its name. 4219;; Make a local copy of FILE and return its name.
diff --git a/lisp/net/tramp-compat.el b/lisp/net/tramp-compat.el
index c554a8d0c2d..9a4e16efe20 100644
--- a/lisp/net/tramp-compat.el
+++ b/lisp/net/tramp-compat.el
@@ -309,6 +309,30 @@ A nil value for either argument stands for the current time."
309 (lambda (filename &optional timestamp _flag) 309 (lambda (filename &optional timestamp _flag)
310 (set-file-times filename timestamp)))) 310 (set-file-times filename timestamp))))
311 311
312;; `directory-files' and `directory-files-and-attributes' got argument
313;; COUNT in Emacs 28.1.
314(defalias 'tramp-compat-directory-files
315 (if (equal (tramp-compat-funcall 'func-arity #'directory-files) '(1 . 5))
316 #'directory-files
317 (lambda (directory &optional full match nosort _count)
318 (directory-files directory full match nosort))))
319
320(defalias 'tramp-compat-directory-files-and-attributes
321 (if (equal (tramp-compat-funcall 'func-arity #'directory-files-and-attributes)
322 '(1 . 6))
323 #'directory-files-and-attributes
324 (lambda (directory &optional full match nosort id-format _count)
325 (directory-files-and-attributes directory full match nosort id-format))))
326
327;; `directory-empty-p' is new in Emacs 28.1.
328(defalias 'tramp-compat-directory-empty-p
329 (if (fboundp 'directory-empty-p)
330 #'directory-empty-p
331 (lambda (dir)
332 (and (file-directory-p dir)
333 (null (tramp-compat-directory-files
334 dir nil directory-files-no-dot-files-regexp t 1))))))
335
312(add-hook 'tramp-unload-hook 336(add-hook 'tramp-unload-hook
313 (lambda () 337 (lambda ()
314 (unload-feature 'tramp-loaddefs 'force) 338 (unload-feature 'tramp-loaddefs 'force)
@@ -322,5 +346,8 @@ A nil value for either argument stands for the current time."
322;; 346;;
323;; * Starting with Emacs 27.1, there's no need to escape open 347;; * Starting with Emacs 27.1, there's no need to escape open
324;; parentheses with a backslash in docstrings anymore. 348;; parentheses with a backslash in docstrings anymore.
349;;
350;; * Starting with Emacs 27.1, there's `make-empty-file'. Could be
351;; used instead of `write-region'.
325 352
326;;; tramp-compat.el ends here 353;;; tramp-compat.el ends here
diff --git a/lisp/net/tramp-gvfs.el b/lisp/net/tramp-gvfs.el
index bf55777e335..86fb45a43b7 100644
--- a/lisp/net/tramp-gvfs.el
+++ b/lisp/net/tramp-gvfs.el
@@ -1088,7 +1088,7 @@ file names."
1088 (delete-file file))) 1088 (delete-file file)))
1089 (directory-files 1089 (directory-files
1090 directory 'full directory-files-no-dot-files-regexp)) 1090 directory 'full directory-files-no-dot-files-regexp))
1091 (when (directory-files directory nil directory-files-no-dot-files-regexp) 1091 (unless (tramp-compat-directory-empty-p directory)
1092 (tramp-error 1092 (tramp-error
1093 v 'file-error "Couldn't delete non-empty %s" directory))) 1093 v 'file-error "Couldn't delete non-empty %s" directory)))
1094 1094
diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el
index 915ce2f6a65..655949a79b8 100644
--- a/lisp/net/tramp-sh.el
+++ b/lisp/net/tramp-sh.el
@@ -1738,6 +1738,9 @@ ID-FORMAT valid values are `string' and `integer'."
1738 (setcar item (expand-file-name (car item) directory))) 1738 (setcar item (expand-file-name (car item) directory)))
1739 (push item result))) 1739 (push item result)))
1740 1740
1741 (when (natnump count)
1742 (setq result (last result count)))
1743
1741 (or (if nosort 1744 (or (if nosort
1742 result 1745 result
1743 (sort result (lambda (x y) (string< (car x) (car y))))) 1746 (sort result (lambda (x y) (string< (car x) (car y)))))
diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el
index ce0a2b54ff5..1859e843758 100644
--- a/lisp/net/tramp.el
+++ b/lisp/net/tramp.el
@@ -3145,7 +3145,7 @@ User is always nil."
3145 (lambda (x) 3145 (lambda (x)
3146 (cons x (file-attributes 3146 (cons x (file-attributes
3147 (if full x (expand-file-name x directory)) id-format))) 3147 (if full x (expand-file-name x directory)) id-format)))
3148 (directory-files directory full match nosort count))) 3148 (tramp-compat-directory-files directory full match nosort count)))
3149 3149
3150(defun tramp-handle-dired-uncache (dir) 3150(defun tramp-handle-dired-uncache (dir)
3151 "Like `dired-uncache' for Tramp files." 3151 "Like `dired-uncache' for Tramp files."
@@ -5346,9 +5346,7 @@ BODY is the backend specific code."
5346 (if (and delete-by-moving-to-trash ,trash) 5346 (if (and delete-by-moving-to-trash ,trash)
5347 ;; Move non-empty dir to trash only if recursive deletion was 5347 ;; Move non-empty dir to trash only if recursive deletion was
5348 ;; requested. 5348 ;; requested.
5349 (if (and (not ,recursive) 5349 (if (not (or ,recursive (tramp-compat-directory-empty-p ,directory)))
5350 (directory-files
5351 ,directory nil directory-files-no-dot-files-regexp))
5352 (tramp-error 5350 (tramp-error
5353 v 'file-error "Directory is not empty, not moving to trash") 5351 v 'file-error "Directory is not empty, not moving to trash")
5354 (move-file-to-trash ,directory)) 5352 (move-file-to-trash ,directory))
diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el
index 50db55ebb4f..2670723ecdc 100644
--- a/test/lisp/net/tramp-tests.el
+++ b/test/lisp/net/tramp-tests.el
@@ -2783,8 +2783,9 @@ This tests also `file-directory-p' and `file-accessible-directory-p'."
2783 (should-not (file-directory-p tmp-name1)) 2783 (should-not (file-directory-p tmp-name1))
2784 2784
2785 ;; Trashing directories works only since Emacs 27.1. It doesn't 2785 ;; Trashing directories works only since Emacs 27.1. It doesn't
2786 ;; work for crypted remote directories. 2786 ;; work for crypted remote directories and for ange-ftp.
2787 (when (and (not (tramp--test-crypt-p)) (tramp--test-emacs27-p)) 2787 (when (and (not (tramp--test-crypt-p)) (not (tramp--test-ftp-p))
2788 (tramp--test-emacs27-p))
2788 (let ((trash-directory (tramp--test-make-temp-name 'local quoted)) 2789 (let ((trash-directory (tramp--test-make-temp-name 'local quoted))
2789 (delete-by-moving-to-trash t)) 2790 (delete-by-moving-to-trash t))
2790 (make-directory trash-directory) 2791 (make-directory trash-directory)
@@ -2925,7 +2926,15 @@ This tests also `file-directory-p' and `file-accessible-directory-p'."
2925 '("bla" "foo"))) 2926 '("bla" "foo")))
2926 (should (equal (directory-files 2927 (should (equal (directory-files
2927 tmp-name1 'full directory-files-no-dot-files-regexp) 2928 tmp-name1 'full directory-files-no-dot-files-regexp)
2928 `(,tmp-name2 ,tmp-name3)))) 2929 `(,tmp-name2 ,tmp-name3)))
2930 ;; Check the COUNT arg. It exists since Emacs 28.
2931 (when (tramp--test-emacs28-p)
2932 (with-no-warnings
2933 (should
2934 (= 1 (length
2935 (directory-files
2936 tmp-name1 nil directory-files-no-dot-files-regexp
2937 nil 1)))))))
2929 2938
2930 ;; Cleanup. 2939 ;; Cleanup.
2931 (ignore-errors (delete-directory tmp-name1 'recursive)))))) 2940 (ignore-errors (delete-directory tmp-name1 'recursive))))))
@@ -3443,7 +3452,13 @@ They might differ only in time attributes or directory size."
3443 (file-attributes (car elt)) (cdr elt)))) 3452 (file-attributes (car elt)) (cdr elt))))
3444 3453
3445 (setq attr (directory-files-and-attributes tmp-name2 nil "\\`b")) 3454 (setq attr (directory-files-and-attributes tmp-name2 nil "\\`b"))
3446 (should (equal (mapcar #'car attr) '("bar" "boz")))) 3455 (should (equal (mapcar #'car attr) '("bar" "boz")))
3456
3457 ;; Check the COUNT arg. It exists since Emacs 28.
3458 (when (tramp--test-emacs28-p)
3459 (with-no-warnings
3460 (should (= 1 (length (directory-files-and-attributes
3461 tmp-name2 nil "\\`b" nil nil 1)))))))
3447 3462
3448 ;; Cleanup. 3463 ;; Cleanup.
3449 (ignore-errors (delete-directory tmp-name1 'recursive)))))) 3464 (ignore-errors (delete-directory tmp-name1 'recursive))))))