Subject: Re: bug#35367: 26.2; `dired-copy-how-to-fn' and HOW-TO arg of `dired-create-files'

From: Mike Kupfer <[email-masked]>
Date: Wed, 10 Jul 2019 22:51:11 -0700

Lars Ingebrigtsen wrote:

> Drew Adams <[email-masked]> writes:
> 
> > 1. I believe `dired-copy-how-to-fn' was added to Emacs quite a while ago
> >    (1991[1]).

lisp/ChangeLog.8 in the 25.3 tarball attributes the change to Inge
Frick, with a date of 1999-09-14 (a couple days before the date listed
in bug#25075).

> > But it's not clear to me what it's really for, and there
> >    seem to be no uses of it in the distributed Emacs code, apart from
> >    `dired-do-copy', which just passes it on to `dired-create-files'.
> >    The variable's doc just says to "See HOW-TO argument for
> >    `dired-create-files'."
> >
> >    So why was this variable created?

Presumably it's so you could override dired's behavior for handling a
target.  If the target is a symlink to a directory, the default behavior
would be to treat it as a directory, but maybe there are cases where you
want to replace the link instead.

The bit about

   If it return value is a list, TARGET is a generalized
    directory (e.g. some sort of archive).  The first element of
    this list must be a function with at least four arguments:

looks like it might be useful when the target is, for example, a tar
file.  By default, copying a single file would replace the tar file.
But this could be overridden (I think) to add or replace entries in the
tar file.

Besides the possibility of a user setting dired-copy-how-to-fn, I can
imagine a package might want to dynamically rebind dired-copy-how-to-fn,
perhaps as a buffer-local variable in a dired buffer.  (I'm not sure
what sort of package might want to do that, but it seems like a possible
reason for having a variable.)

> I hoped that the code might throw some light on this variable, but:
> 
> (defun dired-into-dir-with-symlinks (target)
>   (and (file-directory-p target)
>        (not (file-symlink-p target))))
> ;; This may not always be what you want, especially if target is your
> ;; home directory and it happens to be a symbolic link, as is often the
> ;; case with NFS and automounters.  Or if you want to make symlinks
> ;; into directories that themselves are only symlinks, also quite
> ;; common.
> 
> ;; So we don't use this function as value for HOW-TO in
> ;; dired-do-symlink, which has the minor disadvantage of
> ;; making links *into* a symlinked-dir, when you really wanted to
> ;; *overwrite* that symlink.  In that (rare, I guess) case, you'll
> ;; just have to remove that symlink by hand before making your marked
> ;; symlinks.
> 
> (defvar dired-copy-how-to-fn nil
>   "Either nil or a function used by `dired-do-copy' to determine target.
> See HOW-TO argument for `dired-do-create-files'.")
> 
> It's still clear as mud to me.

dired-into-dir-with-symlinks returns t if TARGET is a real directory.
It returns nil if TARGET is a plain file or a symlink to a directory.
The first generation automounter(s) mounted your home directory in a
temporary directory and then created a symlink to the mounted directory.
But $HOME would be the path to the symlink.

> My interpretation of t is that all files you copy will up in the same
> file if it's t, which is a supremely useless thing, you'd think...

No, you can only copy one file if the target is a plain file.  From
earlier in the docstring for dired-do-create-files:

    The target may also be a non-directory file, if only
    one file is marked.

Maybe this sentence should be deleted:

    Otherwise, the target is a plain file;
    an error is raised unless there is exactly one marked file.

The way the docstring is currently written, it seems to imply that the
error only gets raised in the case where HOW-TO is nil.

I agree that this is all very complicated and confusing.  It doesn't
help that if HOW-TO is t, the target is treated as a plain file.  But if
HOW-TO is a function, it returns nil to indicate a plain file.

mike