Subject: bug#7617: 24.0.50; `expand-file-name': removal of slashes

From: Eli Zaretskii <[email-masked]>
Date: Sun, 12 Dec 2010 10:58:26 -0500

> From: "Drew Adams" <[email-masked]>
> Date: Sat, 11 Dec 2010 13:53:38 -0800
> Cc: 
> 
> emacs -Q
>  
> (expand-file-name "share/" "~/today//usr/") ->
> c:/today/usr/share/.
> 
> (On my Windows laptop, `~' is just `c:/'.)
> 
> IOW, multiple consecutive slashes are collapsed to one.

Correct.

> This is not the behavior I want.  This behavior started in Emacs 21;
> in Emacs 20 no such removal of slashes occurs.

Indeed, this change was made in preparation for release of Emacs 21.1:

  2001-03-02  Gerd Moellmann  <[email-masked]>

	  * fileio.c (Fexpand_file_name): Collapse sequences of slashes
	  to a single slash in the middle of file names.

> I would consider this loss of slashes a bug.

Please explain why you consider this a bug.  foo//bar is at best
equivalent to foo/bar, and at worst simply fails various system calls
and naive Lisp code that doesn't expect more than one slash in a row.

> But I see that comments in
> the current C code indicate that it is intentional (but not _why_).

I didn't find any related discussions that would explain the immediate
reasons for the above change.  So I don't know (and certainly don't
remember ;-) why it was made.  But I do think it's the right behavior
for expand-file-name, because other primitives and Lisp code normally
expects a canonicalized file name, so it would make sense to have a
single primitive that produces such canonicalized file names.

> I don't have C source for Emacs 21, but the behavior of 21 indicates that
> that is when the change was made, presumably intentionally.  I searched
> the change logs but found no mention of this change or why it was made.

See above, for the change log, but it is not really helpful in saying
why (nor should it be).  I haven't found anything in NEWS, either.

> Given that the change was presumably intentional (but why?), you might
> not be disposed to consider this a bug.  I imagine you might argue that
> the second arg to `expand-file-name' in this case is not a valid
> directory name, so all bets are off wrt the behavior - or something like
> that.  Or perhaps you will argue that `expand*' is supposed to give you
> a canonicalized file name, and a name such as "c:/today//usr/share/"
> cannot be said to be canonicalized.

Right, on both counts.

> But shouldn't `expand-file-name' do the right thing if the second arg is
> in fact `file-directory-p'?
> 
> For a user on GNU/Linux with $HOME = /home/toto":
> (file-directory-p "~/today//usr") -> nil, but
> (file-directory-p "~//usr/") --> t, and we have the same problem:
> (expand-file-name "foo" "~//usr/") -> "/home/toto/usr/foo"
>  
> Surely the behavior here is buggy, no?

Sorry, I don't see a bug here.  Please explain more.

> The result should be "/home/toto//usr/foo", I would think.

Not clear why.  As I said, "/home/toto//usr/foo" is at best equivalent
to "/home/toto/usr/foo", and at worst will simply fail in another
place.  So what does the former give you that the latter doesn't?

> _Why should_ `expand-file-name' collapse multiple consecutive
> slashes into a single slash?

In order to produce a _canonicalized_ file name.

> Finally, I need the Emacs 20 behavior for this for some of my code.

Can you describe the use-case where the old behavior is needed?

> Oh, and another thing.  This behavior of `expand-file-name' is not documented.

Well, one could argue that "canonicalized" does mean removing
consecutive slashes, but I guess it's easy enough to say that
explicitly in the doc string.