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

Fix inconsistent link_path behavior #194

Merged
merged 1 commit into from
Sep 1, 2017

Conversation

adamleff
Copy link
Contributor

When calling path on a file using the local transport, it would call Train::Extras::LinuxFile.path which would in turn call read_target_path if the file was a symlink (which calls the readlink OS program). The return value would be stored in @link_path which is then returned whenever link_path is called on the file.

readlink does not operate the same way on macOS like it does on Linux variants. Specifically, in the case of cascading symlinks (a -> b -> c), it will return "c" on Linux but "b" on macOS. This leads to inconsistent behavior depending on if you call path before link_path since path stores a value in @link_path. For example:

Example 1 (calling path before link_path):

inspec> a = file('/tmp/top_link')
=> File /tmp/top_link
inspec> a.path
=> "/tmp/middle_link"
inspec> a.link_path
=> "/tmp/middle_link"

Example 2 (calling link_path before path):

inspec> a = file('/tmp/top_link')
=> File /tmp/top_link
inspec> a.link_path
=> "/private/tmp/actual_file"
inspec> a.path
=> "/private/tmp/actual_file"

Plus, we have the Ruby stdlib calls we can and should use when local so Windows, Linux, and macOS users have a consistent experience. Therefore, this change implements a path method override on the Local File class to avoid LinuxFile from getting in the way.

When calling `path` on a file using the local transport, it would call
Train::Extras::LinuxFile.path which would in turn call read_target_path
if the file was a symlink (which calls the `readlink` OS program). The
return value would be stored in `@link_path` which is then returned whenever
`link_path` is called on the file.

`readlink` does not operate the same way on macOS like it does on Linux
variants. Specifically, in the case of cascading symlinks (a -> b -> c), it will
return "c" on Linux but "b" on macOS. This leads to inconsistent behavior
depending on if you call `path` before `link_path` since `path` stores a value
in `@link_path`. For example:

Example 1 (calling path before link_path):
```
inspec> a = file('/tmp/top_link')
=> File /tmp/top_link
inspec> a.path
=> "/tmp/middle_link"
inspec> a.link_path
=> "/tmp/middle_link"
```

Example 2 (calling link_path before path):
```
inspec> a = file('/tmp/top_link')
=> File /tmp/top_link
inspec> a.link_path
=> "/private/tmp/actual_file"
inspec> a.path
=> "/private/tmp/actual_file"
```

Plus, we have the Ruby stdlib calls we can and should use when
local so Windows, Linux, and macOS users have a consistent experience. Therefore,
this change implements a `path` method override on the Local File class to
avoid LinuxFile from getting in the way.

Signed-off-by: Adam Leff <adam@leff.co>
Copy link
Contributor

@arlimus arlimus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great catch, nice find for this one. Thank you @adamleff

@arlimus arlimus merged commit a68978c into master Sep 1, 2017
@arlimus arlimus deleted the adamleff/fix-link-path-for-local-transport branch September 1, 2017 13:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants