Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Decide if .resolve should work like POSIX realname #5335

Closed
p6rt opened this issue May 22, 2016 · 9 comments
Closed

Decide if .resolve should work like POSIX realname #5335

p6rt opened this issue May 22, 2016 · 9 comments
Labels

Comments

@p6rt
Copy link

p6rt commented May 22, 2016

Migrated from rt.perl.org#128214 (status was 'resolved')

Searchable as RT128214$

@p6rt
Copy link
Author

p6rt commented May 22, 2016

From @AlexDaniel

Code​:
say �../foo/..�.IO.resolve

Result​:
"/home/foo/..".IO

It does not resolve fully! Moreover, if we try something like

Code​:
say �../foo/..�.IO.resolve.dir

Result​:
Failed to get the directory contents of '/home/foo/..'​: chdir failed​: Unknown system error 2
  in any at /home/alex/.rakudobrew/moar-nom/install/share/perl6/runtime/CORE.setting.moarvm line 1
  in block <unit> at -e line 1

Actually thrown at​:
  in block <unit> at -e line 1

Boom!

@p6rt
Copy link
Author

p6rt commented May 23, 2016

From @smls

I works fine for me, provided that ../foo actually exists in the filesystem.

If it doesn't, then `.resolve` leaves anything that comes after it in the path, unchanged​:

  â�� say "sam/..".IO.resolve;
  "/home".IO

  â�� say "nonexistent/..".IO.resolve;
  "/home/nonexistent/..".IO

I'm not sure if it would be theoretically safe for `.resolve` to handle a '..' that comes immediately after the first nonexistent folder name in the path, by simply popping that name off the stack.

But note that POSIX doesn't do it either​:

  $ realpath nonexistent/..
  realpath​: cannot access 'nonexistent/..'​: No such file or directory

Then again, POSIX also doesn't allow '..' to backtrack over an existing non-directory file, whereas Perl 6's `.resolve` does​:

  $ touch a.txt

  $ realpath a.txt/..
  realpath​: a.txt/..​: Not a directory

  $ perl6 -e 'say "a.txt/..".IO.resolve'
  "/home".IO

Do you want to keep this ticket open as an RFC?

@p6rt
Copy link
Author

p6rt commented May 23, 2016

The RT System itself - Status changed from 'new' to 'open'

@p6rt
Copy link
Author

p6rt commented May 23, 2016

From @AlexDaniel

On Mon May 23 10​:02​:18 2016, smls75@​gmail.com wrote​:

I works fine for me, provided that ../foo actually exists in the
filesystem.

If it doesn't, then `.resolve` leaves anything that comes after it in
the path, unchanged​:

� say "sam/..".IO.resolve;
"/home".IO

� say "nonexistent/..".IO.resolve;
"/home/nonexistent/..".IO

I'm not sure if it would be theoretically safe for `.resolve` to
handle a '..' that comes immediately after the first nonexistent
folder name in the path, by simply popping that name off the stack.

But note that POSIX doesn't do it either​:

$ realpath nonexistent/..
realpath​: cannot access 'nonexistent/..'​: No such file or directory

Then again, POSIX also doesn't allow '..' to backtrack over an
existing non-directory file, whereas Perl 6's `.resolve` does​:

$ touch a.txt

$ realpath a.txt/..
realpath​: a.txt/..​: Not a directory

$ perl6 -e 'say "a.txt/..".IO.resolve'
"/home".IO

Do you want to keep this ticket open as an RFC?

You are right, I was wrong.

However, there is a pull request here​: rakudo/rakudo#775

Now, I'm not sure what this pull request does, but I'm pretty sure that the current error message is LTA (Unknown system error 2, huh?). That's not RFC at all though.

So, maybe we should change the title a little bit?

@p6rt
Copy link
Author

p6rt commented May 24, 2016

From @smls

I think this needs an explicit design decision first, that's why I suggested an RFC.

Should `.resolve` ...

a) ...be as strict as POSIX `realname`, i.e. expand the path from left to right, and abort with an error as soon as a nonexistent directory is encountered or when a file is treated like a directory?

b) ...be as lenient as possible, i.e. return a partially-resolved path in case of non-existent parts, and allow `..` to follow an existing non-directory file, etc.?

c) ...something in between?

The comments in src/core/IO/Path.pm suggest that at least one aspect of the current behavior (returning partially-resolved paths), is intentional. This shouldn't be changed unilaterally by a patch "just because Bash does it".

Someone more competent than me should sit down and think through the implications of the different possible `.resolve` behaviors, and come up with design that is deemed optimal for Perl 6 (and doesn't violate existing spec tests due to the Perl 6.c backwards compatibility guarantee).
Oh and be sure to get lizmat on board, because AFAIK she did much of the Perl 6 IO design and implementation work.

@p6rt
Copy link
Author

p6rt commented Jun 2, 2016

From @MasterDuke17

Even if there are no other changes to existing behaviour, I would still
suggest 'warn'ing or 'note'ing when a non-existent part is hit and
resolving is stopped. Or at least changing the documentation, because the
current behaviour is definitely a bit surprising (at least in my opinion).

Dan

@p6rt
Copy link
Author

p6rt commented Jun 2, 2016

From @labster

On Tue May 24 09​:17​:43 2016, smls75@​gmail.com wrote​:

I think this needs an explicit design decision first, that's why I
suggested an RFC.

Should `.resolve` ...

a) ...be as strict as POSIX `realname`, i.e. expand the path from left
to right, and abort with an error as soon as a nonexistent directory
is encountered or when a file is treated like a directory?

b) ...be as lenient as possible, i.e. return a partially-resolved path
in case of non-existent parts, and allow `..` to follow an existing
non-directory file, etc.?

c) ...something in between?

The comments in src/core/IO/Path.pm suggest that at least one aspect
of the current behavior (returning partially-resolved paths), is
intentional. This shouldn't be changed unilaterally by a patch "just
because Bash does it".

When I originally speculated IO​::Path.resolve, I think I was intending for it to return a usable filesystem path in all cases. Or more specifically​:
* resolve all symlinks
* remove all instances of .. and .

And I had another method, IO​::Path.cleanup( parent => True ) which was intended to do logical path cleanup based only on the strings. That's still a real use case for me, though IO​::Spec.canonpath( :$parent ) still exists to provide some more functionality there, even if I do need to create path objects after cleanup instead of before.

So I think I vote for resolve to fail() on a path that tries to find the parent of a nonexistent directory. I can't think of a reason why this would be useful​:
$ perl6 -e 'say "noexist/..".IO.resolve'
"/Users/brent/code/rakudo/noexist/..".IO

So unless someone can come up with an actual use case for the line above, I suggest either​:
* Act like `realname`
* Be more lenient in that we're allowed to .. above files and not just directories.
I'm leaning towards the stricter behavior myself.

Note that there are few spectests running for IO​::Path.resolve yet (there are 3 marked TODO), so I think we still have room to just consider this a plain rakudobug.

@p6rt
Copy link
Author

p6rt commented May 28, 2017

From @zoffixznet

Thank you for the report. This issue is now resolved.

If you wish .resolve to `fail` if it cannot completely resolve the path, set `​:completely` named arg to True​: https://docs.perl6.org/routine/resolve.html

@p6rt
Copy link
Author

p6rt commented May 28, 2017

@zoffixznet - Status changed from 'open' to 'resolved'

@p6rt p6rt closed this as completed May 28, 2017
@p6rt p6rt added the at_larry label Jan 5, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant