Subject: bug#28483: 26.0.50; copy-directory does not create directories

From: Paul Eggert <[email-masked]>
Date: Wed, 20 Sep 2017 11:59:37 -0700

On 09/20/2017 04:26 AM, Eli Zaretskii wrote:
> I think the problem is in this line:
>
> 	  (cond
> 	   ((eq filetype t)       ; Directory but not a symlink.
> 	    (copy-directory file newname keep-time parents)) <<<<<<<<<<<
>
> Instead of 'newname', there should be (file-name-as-directory newname)
> there.  I think.

Thanks for diagnosing the problem and for the fix. That fix should work, 
and I think we can improve on it slightly by using (copy-directory file 
target keep-time parents t), as this makes the cond branch more parallel 
with the other alternatives and avoids a call to file-name-as-directory. 
So I installed the attached patch into the emacs-26 branch to do that, 
and to add a test case for this bug. This patch should also fix 
Bug#28520 "Dired recursive copy of directory fails", so I'll CC: that 
bug report and boldly close it.

PS. Sorry, Adam, for misspelling your first name in the commit message. 
I'll try to remember to fix that when it spills out into the ChangeLog file.

>From b4531a78ded7efb0c133763b5efe1f4dab1aa4de Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email-masked]>
Date: Wed, 20 Sep 2017 11:49:12 -0700
Subject: [PATCH] Fix new copy-directory bug with empty dirs

Problem reported by Afdam Plaice (Bug#28520) and by Eli Zaretskii
(Bug#28483#34).  This is another bug that I introduced in my
recent copy-directory changes.
* lisp/files.el (copy-directory): Work with empty subdirectories, too.
* test/lisp/files-tests.el (files-tests--copy-directory):
Test for this bug.
---
 lisp/files.el            | 2 +-
 test/lisp/files-tests.el | 7 ++++++-
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/lisp/files.el b/lisp/files.el
index 0c30d40c13..f0a1f2380d 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -5564,7 +5564,7 @@ copy-directory
 	      (filetype (car (file-attributes file))))
 	  (cond
 	   ((eq filetype t)       ; Directory but not a symlink.
-	    (copy-directory file newname keep-time parents))
+	    (copy-directory file target keep-time parents t))
 	   ((stringp filetype)    ; Symbolic link
 	    (make-symbolic-link filetype target t))
 	   ((copy-file file target t keep-time)))))
diff --git a/test/lisp/files-tests.el b/test/lisp/files-tests.el
index f2a9a32180..285a884b69 100644
--- a/test/lisp/files-tests.el
+++ b/test/lisp/files-tests.el
@@ -399,11 +399,16 @@ files-tests--with-temp-file
 	 (dirname (file-name-as-directory dir))
 	 (source (concat dirname "source"))
 	 (dest (concat dirname "dest/new/directory/"))
-	 (file (concat (file-name-as-directory source) "file")))
+	 (file (concat (file-name-as-directory source) "file"))
+	 (source2 (concat dirname "source2"))
+	 (dest2 (concat dirname "dest/new2")))
     (make-directory source)
     (write-region "" nil file)
     (copy-directory source dest t t t)
     (should (file-exists-p (concat dest "file")))
+    (make-directory (concat (file-name-as-directory source2) "a") t)
+    (copy-directory source2 dest2)
+    (should (file-directory-p (concat (file-name-as-directory dest2) "a")))
     (delete-directory dir 'recursive)))
 
 (provide 'files-tests)
-- 
2.13.5