Subject: Re: bug#5982: 23.1.96; Dired regression - recursive copies turn symlinks into regular files

From: Chong Yidong <[email-masked]>
Date: Tue, 20 Apr 2010 10:54:27 -0400

Sven Joachim <[email-masked]> writes:

> On 2010-04-20 11:26 +0200, Sven Joachim wrote:
>
>> Suppose we have the following directory in dired:
>>
>> ,----
>> |   /tmp/foo:
>> |   total used in directory 4 available 1674380
>> |   drwxr-xr-x  2 sven sven  80 Apr 20 11:12 .
>> |   drwxrwxrwt 14 root root 300 Apr 20 11:12 ..
>> |   -rw-r--r--  1 sven sven   6 Apr 20 11:09 bar
>> |   lrwxrwxrwx  1 sven sven   3 Apr 20 11:12 bar2 -> bar
>> `----
>>
>> Now type ^ to cd to the parent directory, move to the "foo" line and
>> press "C /tmp/foo2 RET yes" (confirming the recursive copy and creating
>> /tmp/foo2) and switch to the new directory.  It looks like this:
>>
>> ,----
>> |   /tmp/foo2:
>> |   total used in directory 8 available 1674380
>> |   drwxr-xr-x  2 sven sven  80 Apr 20 11:12 .
>> |   drwxrwxrwt 14 root root 300 Apr 20 11:12 ..
>> |   -rw-r--r--  1 sven sven   6 Apr 20 11:09 bar
>> |   -rw-r--r--  1 sven sven   6 Apr 20 11:09 bar2
>> `----
>>
>> This is a regression from Emacs 23.1 and 22.3 where the symlink would be
>> copied as such instead of turning into a regular file.
>
> Bisecting shows that this problem first occured in revision 97979 when
> dired-copy-file-recursive started to use the new copy-directory command
> (added in revision 97978).  The latter just calls copy-file for
> non-directories, and copy-file has no option to preserve symlinks.

The following patch would add symlink copying to `copy-directory'.
Michael, could you review the patch carefully, or suggest some other
solution?

*** lisp/files.el	2010-03-11 16:25:46 +0000
--- lisp/files.el	2010-04-20 14:50:35 +0000
***************
*** 4735,4744 ****
        (mapc
         (lambda (file)
  	 (let ((target (expand-file-name
! 			(file-name-nondirectory file) newname)))
! 	   (if (file-directory-p file)
! 	       (copy-directory file target keep-time parents)
! 	     (copy-file file target t keep-time))))
         ;; We do not want to copy "." and "..".
         (directory-files	directory 'full directory-files-no-dot-files-regexp))
  
--- 4735,4748 ----
        (mapc
         (lambda (file)
  	 (let ((target (expand-file-name
! 			(file-name-nondirectory file) newname))
! 	       (attrs (file-attributes file)))
! 	   (cond ((file-directory-p file)
! 		  (copy-directory file target keep-time parents))
! 		 ((stringp (car attrs)) ; Symbolic link
! 		  (make-symbolic-link (car attrs) target t))
! 		 (t
! 		  (copy-file file target t keep-time)))))
         ;; We do not want to copy "." and "..".
         (directory-files	directory 'full directory-files-no-dot-files-regexp))