On 13/05/07, Nobuyoshi Nakada <nobu / ruby-lang.org> wrote:
> Hi,
>
> At Sun, 13 May 2007 02:07:13 +0900,
> Austin Ziegler wrote in [ruby-core:11161]:
> > On 5/12/07, Nobuyoshi Nakada <nobu / ruby-lang.org> wrote:
> > > At Fri, 16 Feb 2007 02:09:08 +0900,
> > > Daniel Berger wrote in [ruby-core:10321]:
> > > > The File.basename method does not work properly on Windows
> > > > root paths. IMO, calling File.basename on a root path should
> > > > return itself. However, on MS Windows it appears to be
> > > > dropping the volume name and it doesn't handle UNC root paths
> > > > correctly:
> > > Drive letter is part of base name?  It feels very strange to me.
> >
> > It's right, though.
> >
> > File.basename("C:/") should return "C:/"
> > File.dirname("C:/") should return "C:/"
> > File.basename("//server/share/") must return "//server/share/"
> > File.dirname("//server/share/") must return "//server/share/"
>
> What's the reason?  Do you consider a drive letter to be a part
> of basename?
>
> And if they were work so, then File.join(*File.split("C:/"))
> should return "C:/C:/", but it is incorrect on Windows.  Is it
> what you want?
>
> > This would be true for any filesystem environment that allows multiple roots.
>
> Really?  Do you know other such environments?
>
When you include some sort of networking into file path you usually
get multiple roots. In some cases this can be abstracted as single
root that includes the hostname but you would usually also get some
sort of shortcut for local files. Sure, systems that include such
things are either obscure or Windows.

I would the basename and dirname to preserve two invariants:

given

class String
 def basename
  File.basename self
 end
 def dirname
  FIle.dirname self
 end
end

I)
(s.dirname + File::SEPARATOR + s.basename) should refer to the same
file as (s) as long as neither s.dirname nor s.basename is empty. This
breaks with the concept of "current directory" in Windows.

II)
(s + File::SEPARATOR).dirname == s.dirname
(s + File::SEPARATOR).basename == s.basename

However, this cannot be preserved in cases when adding the separator
changes path designation as understood by the OS ( "C:" is not the
same as "C:/" but "C:/a" and "C:/a/" hopefully is).

III)

s.dirname should be "" only if s does not contain directory specification.
On unix directory specification is only File::SEPARATOR but on Windows
"C:" alone is also a directory specification but does not contain any
separator.

s.basename should not be empty nor the separator. But "C:" is a
directory specification which cannot be split. "C:".dirname must be
"C:" to specify the directory, and "C:".basename must be "", "." would
not work ( "C:" + "/" + ".") is something else.
The same goes for "C:/" and unix "/" except "." or "/" would be
probably an acceptable basename as well. We might specify that
basename for roots is "" which would solve all cases in POSIX and
Windows.

Still the windows programmer must be careful and check for empty
basename while the unix programmer does not have to.
Also there is the case "C:file" which refers to file in the current
directory on C. This cannot be reasonably split so that adding the
separator would yield the same result. It might work if "C:." and
"C:./file" are valid and do the expected thing.

Thanks

Michal