diff options
| author | Paul Eggert | 2022-12-17 12:15:30 -0800 |
|---|---|---|
| committer | Paul Eggert | 2022-12-17 14:24:16 -0800 |
| commit | 44c83b239d3cbb5c7675c8abd595fd3e33811ece (patch) | |
| tree | 3fc699a64bc53b76b34c55cffdb7d3735b4afde9 | |
| parent | bef1edc9cacb976120dff73b4d7bbdce6ade982b (diff) | |
| download | emacs-44c83b239d3cbb5c7675c8abd595fd3e33811ece.tar.gz emacs-44c83b239d3cbb5c7675c8abd595fd3e33811ece.zip | |
Fix copy-directory bug when dest dir exists
* lisp/files.el (copy-directory): Set ‘follow’ depending on
whether we made the directory, not based on a guess that is
sometimes wrong. When NEWNAME is a directory name and
COPY-CONTENTS is nil, do not object merely because the adjusted
NEWNAME is already a directory. (Bug#58919).
* test/lisp/files-tests.el (files-tests-copy-directory):
Test for the bug.
| -rw-r--r-- | lisp/files.el | 19 | ||||
| -rw-r--r-- | test/lisp/files-tests.el | 9 |
2 files changed, 20 insertions, 8 deletions
diff --git a/lisp/files.el b/lisp/files.el index 235eacee704..3cf7833ae02 100644 --- a/lisp/files.el +++ b/lisp/files.el | |||
| @@ -6437,7 +6437,7 @@ into NEWNAME instead." | |||
| 6437 | ;; copy-directory handler. | 6437 | ;; copy-directory handler. |
| 6438 | (let ((handler (or (find-file-name-handler directory 'copy-directory) | 6438 | (let ((handler (or (find-file-name-handler directory 'copy-directory) |
| 6439 | (find-file-name-handler newname 'copy-directory))) | 6439 | (find-file-name-handler newname 'copy-directory))) |
| 6440 | (follow parents)) | 6440 | follow) |
| 6441 | (if handler | 6441 | (if handler |
| 6442 | (funcall handler 'copy-directory directory | 6442 | (funcall handler 'copy-directory directory |
| 6443 | newname keep-time parents copy-contents) | 6443 | newname keep-time parents copy-contents) |
| @@ -6457,19 +6457,24 @@ into NEWNAME instead." | |||
| 6457 | t) | 6457 | t) |
| 6458 | (make-symbolic-link target newname t))) | 6458 | (make-symbolic-link target newname t))) |
| 6459 | ;; Else proceed to copy as a regular directory | 6459 | ;; Else proceed to copy as a regular directory |
| 6460 | (cond ((not (directory-name-p newname)) | 6460 | ;; first by creating the destination directory if needed, |
| 6461 | ;; preparing to follow any symlink to a directory we did not create. | ||
| 6462 | (setq follow | ||
| 6463 | (if (not (directory-name-p newname)) | ||
| 6461 | ;; If NEWNAME is not a directory name, create it; | 6464 | ;; If NEWNAME is not a directory name, create it; |
| 6462 | ;; that is where we will copy the files of DIRECTORY. | 6465 | ;; that is where we will copy the files of DIRECTORY. |
| 6463 | (make-directory newname parents)) | 6466 | (make-directory newname parents) |
| 6464 | ;; NEWNAME is a directory name. If COPY-CONTENTS is non-nil, | 6467 | ;; NEWNAME is a directory name. If COPY-CONTENTS is non-nil, |
| 6465 | ;; create NEWNAME if it is not already a directory; | 6468 | ;; create NEWNAME if it is not already a directory; |
| 6466 | ;; otherwise, create NEWNAME/[DIRECTORY-BASENAME]. | 6469 | ;; otherwise, create NEWNAME/[DIRECTORY-BASENAME]. |
| 6467 | ((if copy-contents | 6470 | (unless copy-contents |
| 6468 | (or parents (not (file-directory-p newname))) | ||
| 6469 | (setq newname (concat newname | 6471 | (setq newname (concat newname |
| 6470 | (file-name-nondirectory directory)))) | 6472 | (file-name-nondirectory directory)))) |
| 6471 | (make-directory (directory-file-name newname) parents)) | 6473 | (condition-case err |
| 6472 | (t (setq follow t))) | 6474 | (make-directory (directory-file-name newname) parents) |
| 6475 | (error | ||
| 6476 | (or (file-directory-p newname) | ||
| 6477 | (signal (car err) (cdr err))))))) | ||
| 6473 | 6478 | ||
| 6474 | ;; Copy recursively. | 6479 | ;; Copy recursively. |
| 6475 | (dolist (file | 6480 | (dolist (file |
diff --git a/test/lisp/files-tests.el b/test/lisp/files-tests.el index b9fbeb8a4e0..011bfa67cc2 100644 --- a/test/lisp/files-tests.el +++ b/test/lisp/files-tests.el | |||
| @@ -1346,7 +1346,9 @@ name (Bug#28412)." | |||
| 1346 | (dest (concat dirname "dest/new/directory/")) | 1346 | (dest (concat dirname "dest/new/directory/")) |
| 1347 | (file (concat (file-name-as-directory source) "file")) | 1347 | (file (concat (file-name-as-directory source) "file")) |
| 1348 | (source2 (concat dirname "source2")) | 1348 | (source2 (concat dirname "source2")) |
| 1349 | (dest2 (concat dirname "dest/new2"))) | 1349 | (dest2 (concat dirname "dest/new2")) |
| 1350 | (source3 (concat dirname "source3/d")) | ||
| 1351 | (dest3 (concat dirname "dest3/d"))) | ||
| 1350 | (make-directory source) | 1352 | (make-directory source) |
| 1351 | (write-region "" nil file) | 1353 | (write-region "" nil file) |
| 1352 | (copy-directory source dest t t t) | 1354 | (copy-directory source dest t t t) |
| @@ -1354,6 +1356,11 @@ name (Bug#28412)." | |||
| 1354 | (make-directory (concat (file-name-as-directory source2) "a") t) | 1356 | (make-directory (concat (file-name-as-directory source2) "a") t) |
| 1355 | (copy-directory source2 dest2) | 1357 | (copy-directory source2 dest2) |
| 1356 | (should (file-directory-p (concat (file-name-as-directory dest2) "a"))) | 1358 | (should (file-directory-p (concat (file-name-as-directory dest2) "a"))) |
| 1359 | (make-directory source3 t) | ||
| 1360 | (write-region "x\n" nil (concat (file-name-as-directory source3) "file")) | ||
| 1361 | (make-directory dest3 t) | ||
| 1362 | (write-region "y\n" nil (concat (file-name-as-directory dest3) "file")) | ||
| 1363 | (copy-directory source3 (file-name-directory dest3) t) | ||
| 1357 | (delete-directory dir 'recursive)))) | 1364 | (delete-directory dir 'recursive)))) |
| 1358 | 1365 | ||
| 1359 | (ert-deftest files-tests-abbreviate-file-name-homedir () | 1366 | (ert-deftest files-tests-abbreviate-file-name-homedir () |