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

Use std::filesystem in canonPath and local store symlink detection #11871

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

puffnfresh
Copy link
Member

Motivation

Nix on Windows.

Context

Local store wouldn't work on Windows due to an infinite loop (paths never become "/" on Windows)

Canon path was always prepending the root path (e.g. D:/) which ended up with silly paths (e.g. D:/D:/nix/store) and it was quite a complicated function.

Priorities and Process

Add 👍 to pull requests you find important.

The Nix maintainer team uses a GitHub project board to schedule and track reviews.

@github-actions github-actions bot added the store Issues and pull requests concerning the Nix store label Nov 12, 2024
Comment on lines +96 to +103
while (!result.has_filename() && result.has_parent_path())
{
// The parent of "D:/" is "D:/" so we need to be careful.
fs::path parent = result.parent_path();
if (parent == result)
break;
result = parent;
}
Copy link
Member

Choose a reason for hiding this comment

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

I think a lexically_normal path can have at most one trailing separator, so you probably don't need a while loop here?

Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
while (!result.has_filename() && result.has_parent_path())
{
// The parent of "D:/" is "D:/" so we need to be careful.
fs::path parent = result.parent_path();
if (parent == result)
break;
result = parent;
}
if (result.has_parent_path()) result = result.parent_path();

Comment on lines +89 to +92
// This function used to resolve 1024 symlinks via a custom implementation.
// The standard filesystem library will behave differently. For example,
// libstd++ in GCC will only resolve 40 symlinks.
// I hope that isn't a problem!
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// This function used to resolve 1024 symlinks via a custom implementation.
// The standard filesystem library will behave differently. For example,
// libstd++ in GCC will only resolve 40 symlinks.
// I hope that isn't a problem!
// This function used to resolve 1024 symlinks via a custom implementation.
// The standard filesystem library will behave differently. For example,
// libstd++ in GCC will only resolve 40 symlinks.
// I hope that isn't a problem!

This kind of historical comment is best put in the Git commit message.

It is worth noting what happens if the recursion limit is exceeded. Does it throw an exception?

Copy link
Member

Choose a reason for hiding this comment

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

https://en.cppreference.com/w/cpp/filesystem/path/lexically_normal says

Exceptions

May throw implementation-defined exceptions.

Great, lol

@Ericson2314 Ericson2314 changed the title Use std::filesystem in canonPath and local store symlink detection Use std::filesystem in canonPath and local store symlink detection Nov 13, 2024
std::filesystem::path path = realStoreDir.get();
std::filesystem::path root = path.root_path();
while (path != root) {
if (std::filesystem::is_symlink(path))
Copy link
Member

@Mic92 Mic92 Nov 19, 2024

Choose a reason for hiding this comment

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

Would be nice to wrap is_symlink in an try-catch and re-throw a nix error instead the original exception that std::filesystem throws because those actually will have an error trace added when the exception is bubbled up.

Copy link
Member

Choose a reason for hiding this comment

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

The function rethrowExceptionAsError() can be used for that. (Should be moved from local-derivation-goal.cc to libutil, probably.)

Copy link
Member

Choose a reason for hiding this comment

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

Ok. Just make sure rethrowExceptionAsError() properly also logs paths as well this way so that users have a clue what goes wrong.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
store Issues and pull requests concerning the Nix store
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants