Jon Fairbairn | 26 Sep 16:30 2012
X-Face
Picon
Picon

makeRelative


I have an application where I want to use relative paths in
symlinks (so that rsyncing to a different machine with a
different root directory produces something with the same
effect).

So I want

makeRelative "/var/www/this_server/foo/bar/" "/var/www/this_server/bob"

to return "../../bob" (which would then be used to create a
symlink) so that if I copy the tree below /var/www/this_server
to /var/www/that_server (perhaps on a different machine, but
copying the symlinks without rewriting them), the symlinks point
to the same files.

On posix at least, this would permit isRelative (makeRelative a
b) always to be True, which is a pleasant property for it to
have.

Is there any reason that System.FilePath.Posix.makeRelative should not
do this? I don’t know enough about non-posix filesystems to know
whether it even makes sense elsewhere.

--

-- 
Jón Fairbairn                                 Jon.Fairbairn <at> cl.cam.ac.uk

_______________________________________________
Libraries mailing list
Libraries <at> haskell.org
(Continue reading)

Ian Lynagh | 26 Sep 16:47 2012

Re: makeRelative

On Wed, Sep 26, 2012 at 03:30:50PM +0100, Jon Fairbairn wrote:
> 
> I have an application where I want to use relative paths in
> symlinks (so that rsyncing to a different machine with a
> different root directory produces something with the same
> effect).
> 
> So I want
> 
> makeRelative "/var/www/this_server/foo/bar/" "/var/www/this_server/bob"
> 
> to return "../../bob" (which would then be used to create a
> symlink) so that if I copy the tree below /var/www/this_server
> to /var/www/that_server (perhaps on a different machine, but
> copying the symlinks without rewriting them), the symlinks point
> to the same files.
> 
> On posix at least, this would permit isRelative (makeRelative a
> b) always to be True, which is a pleasant property for it to
> have.
> 
> Is there any reason that System.FilePath.Posix.makeRelative should not
> do this? I don’t know enough about non-posix filesystems to know
> whether it even makes sense elsewhere.

Coincidentally, I needed this yesterday, was also surprised to find it
missing, and wrote:

    makeRelativeTo :: FilePath -> FilePath -> FilePath
    this `makeRelativeTo` that = directory </> thisFilename
(Continue reading)

Jon Fairbairn | 28 Sep 10:50 2012
X-Face
Picon
Picon

Re: makeRelative

Ian Lynagh <ian <at> well-typed.com> writes:

> On Wed, Sep 26, 2012 at 03:30:50PM +0100, Jon Fairbairn wrote:
>> 
>> I have an application where I want to use relative paths in
>> symlinks […]
>> 
>> So I want
>> 
>> makeRelative "/var/www/this_server/foo/bar/" "/var/www/this_server/bob"
>> 
>> to return "../../bob" […]
>> 
>> On posix at least, this would permit isRelative (makeRelative a
>> b) always to be True, which is a pleasant property for it to
>> have.
>> 
>> Is there any reason that System.FilePath.Posix.makeRelative should not
>> do this? I don’t know enough about non-posix filesystems to know
>> whether it even makes sense elsewhere.
>
> Coincidentally, I needed this yesterday

So evidently it is useful, and at least two people think it
should work this way :-)

> (in my case, I know that both paths are absolute).

I wrote something similar, but with calls to isAbsolute and use
of System.FilePath.makeRelative
(Continue reading)

Herbert Valerio Riedel | 28 Sep 22:16 2012
Picon

Re: makeRelative

Jon Fairbairn <jon.fairbairn <at> cl.cam.ac.uk> writes:

> So I want
>
> makeRelative "/var/www/this_server/foo/bar/" "/var/www/this_server/bob"
>
> to return "../../bob" 

[...]

> Is there any reason that System.FilePath.Posix.makeRelative should not
> do this? I don’t know enough about non-posix filesystems to know
> whether it even makes sense elsewhere.

I don't know whether this might the reason (or whether it is relevant at
all for the API at hand) but you can't implement this function properly
w/o turning it into an IO action, since you need to be able to
introspect the filesystem, because under POSIX at least, you can easily
construct a filesystem, which exhibits the following confusing
behaviour:

,----
| /tmp/xxx$ pwd
| /tmp/xxx
| /tmp/xxx$ ls -l bar
| total 0
| -rw-rw-r-- 1 hvr hvr 0 Sep 28 22:03 this_is_in_xxx
| /tmp/xxx$ cd bar
| /tmp/xxx/bar$ ls -l
| total 0
(Continue reading)

Jon Fairbairn | 30 Sep 11:36 2012
X-Face
Picon
Picon

Re: makeRelative

Herbert Valerio Riedel <hvr <at> gnu.org> writes:

> Jon Fairbairn <jon.fairbairn <at> cl.cam.ac.uk> writes:
>
>> So I want
>>
>> makeRelative "/var/www/this_server/foo/bar/" "/var/www/this_server/bob"
>>
>> to return "../../bob" 
>
> [...]
>
>> Is there any reason that System.FilePath.Posix.makeRelative should not
>> do this? I don’t know enough about non-posix filesystems to know
>> whether it even makes sense elsewhere.
>
> I don't know whether this might the reason (or whether it is relevant at
> all for the API at hand) but you can't implement this function properly
> w/o turning it into an IO action

Ah, well spotted. In my use case I happen to know the structure
of the directories, so hadn’t considered that symlinks can make
it impossible to do purely. Given that in System.Directory there
is

 makeRelativeToCurrentDirectory:: FilePath -> IO FilePath,

we should probably have a function in there 

 makeRelativeToPath:: FilePath -> FilePath -> IO FilePath.
(Continue reading)

Ben Millwood | 30 Sep 16:24 2012
Picon

Re: makeRelative

On Fri, Sep 28, 2012 at 9:16 PM, Herbert Valerio Riedel <hvr <at> gnu.org> wrote:
> I don't know whether this might the reason (or whether it is relevant at
> all for the API at hand) but you can't implement this function properly
> w/o turning it into an IO action, since you need to be able to
> introspect the filesystem, because under POSIX at least, you can easily
> construct a filesystem, which exhibits the following confusing
> behaviour:

I have two comments on this behaviour:

1. "confusing" is not the same as "wrong"
2. surely this issue can be avoided by using something like
System.Directory.canoncalizePath before calling makeRelative. I think
doing things that way would separate the pure and IO parts of the
algorithm much better, and allow users to ignore the possibility of
symlinks when that was appropriate for their use.
Ian Lynagh | 30 Sep 17:35 2012
Picon

Re: makeRelative

On Sun, Sep 30, 2012 at 03:24:14PM +0100, Ben Millwood wrote:
> On Fri, Sep 28, 2012 at 9:16 PM, Herbert Valerio Riedel <hvr <at> gnu.org> wrote:
> > I don't know whether this might the reason (or whether it is relevant at
> > all for the API at hand) but you can't implement this function properly
> > w/o turning it into an IO action, since you need to be able to
> > introspect the filesystem, because under POSIX at least, you can easily
> > construct a filesystem, which exhibits the following confusing
> > behaviour:
> 
> I have two comments on this behaviour:
> 
> 1. "confusing" is not the same as "wrong"
> 2. surely this issue can be avoided by using something like
> System.Directory.canoncalizePath before calling makeRelative. I think
> doing things that way would separate the pure and IO parts of the
> algorithm much better, and allow users to ignore the possibility of
> symlinks when that was appropriate for their use.

In my use, at least one of the paths didn't actually exist on the
filesystem, so canonicalising the path would have failed.

Thanks
Ian
wren ng thornton | 30 Sep 20:26 2012

Re: makeRelative

On 9/30/12 10:24 AM, Ben Millwood wrote:
> 2. surely this issue can be avoided by using something like
> System.Directory.canoncalizePath before calling makeRelative. I think
> doing things that way would separate the pure and IO parts of the
> algorithm much better, and allow users to ignore the possibility of
> symlinks when that was appropriate for their use.

Indeed. While it's important to be able to capture correct POSIX 
behavior, there's also plenty of room for legitimate uses of naive 
relative paths. In particular, the former is more important when 
accessing the filesystem, whereas the latter is more important when 
generating files[1].

So long as the documentation includes das blinkenlights, to ensure that 
users know which behavior they're getting, I think it's fine to offer 
the naive implementation. If folks consider it "unsafe" enough to 
warrant name changes, we could always:

     canoncalizePath :: Path -> IO Path

     naiveMakeRelative :: Path -> Path -> Path

     makeRelative x y = do
         x <- canoncalizePath x
         y <- canoncalizePath y
         return $! naiveMakeRelative x y

[1] Because you know the filesystem structure you'll be generating, so 
you know whether this will be an issue. And because the files you'll be 
generating don't yet exist and so can't be cannonicalized, as others 
(Continue reading)


Gmane