-
Notifications
You must be signed in to change notification settings - Fork 5.9k
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
Stripping base path from CLI paths (without CLI refactor) #11617
Stripping base path from CLI paths (without CLI refactor) #11617
Conversation
In case anyone is wondering why this is so much more complex than my initial PR, here's a non-exhaustive list of path-related weirdness it has to account for:
|
libsolidity/interface/FileReader.h
Outdated
@@ -83,7 +84,51 @@ class FileReader | |||
return [this](std::string const& _kind, std::string const& _path) { return readFile(_kind, _path); }; | |||
} | |||
|
|||
/// Normalizes a filesystem path in a way that removes small, inconsequential differences. Specifically: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe just sommarize in the header and put the full description in the cpp file?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure. I thought the docstring would be a better place for this. It is a bit detailed but on the other hand it still describes the effects visible to the user of the function rather than implementation details.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
Did not review the actual code. |
46ac037
to
a9c06fb
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approved
libsolidity/interface/FileReader.cpp
Outdated
); | ||
|
||
string rootName = normalizedPath.root_name().string(); | ||
boost::filesystem::path normalizedRootPath = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it really correct to define normalizedRootPath
here again?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch. It should not be redeclared. Weird that it did not break any tests though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed. The normalization from \\host
and //host
for UNC paths was broken because of this. Tests did not break because boost ignores slashes is comparisons. Slashes do not matter as long as we use generic_string()
on the path before using it but better have it normalized in case someone uses native()
instead.
0d67e71
to
6eaf232
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some minor comments, looks good in general
/// Paths are treated as case-sensitive. Does not require the path to actually exist in the | ||
/// filesystem and does not follow symlinks. Only considers whole segments, e.g. /abc/d is not | ||
/// considered a prefix of /abc/def. Both paths must be non-empty. | ||
static bool isPathPrefix(boost::filesystem::path _prefix, boost::filesystem::path const& _path); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any particular reason _prefix
is not const&
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm modifying it in place inside the function. I could add a local variable but it was just more convenient to modify the parameter.
/// If @a _prefix is actually a prefix of @p _path, removes it from @a _path to make it relative. | ||
/// Otherwise returns @a _path unchanged. | ||
/// Returns '.' if @a _path and @_prefix are identical. | ||
static boost::filesystem::path stripPrefixIfPresent(boost::filesystem::path _prefix, boost::filesystem::path const& _path); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here re const&
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_prefix.remove_filename(); | ||
|
||
boost::filesystem::path strippedPath = _path.lexically_relative(_prefix); | ||
solAssert(strippedPath.empty() || *strippedPath.begin() != "..", ""); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So each element of strippedPath
is a string?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's actually path
but strings are implicitly convertible to that type.
Boost let you iterate over path segments while skipping separators. E.g. in /a/bc/def.sol
you can iterate over a
, bc
and def.sol
.
rootName.size() == 2 || | ||
(rootName.size() > 2 && rootName[2] != rootName[1]) | ||
) && ( | ||
(rootName[0] == '/' && rootName[1] == '/') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why both?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mean "why both characters should be /
" or "why both //
and \\
"?
If it's the former - this is meant to detect UNC paths of the form //host/a/bc/def.sol
.
If the latter: Windows accepts both //host
and \\host
as UNC path root name. Outside of windows only the one starting with //
is treated specially.
BOOST_TEST(FileReader::normalizeCLIPathForVFS("/a/b/c/../") == "/a/b/"); | ||
|
||
BOOST_TEST(FileReader::normalizeCLIPathForVFS("/a/b/c/../../..") == "/"); | ||
BOOST_TEST(FileReader::normalizeCLIPathForVFS("/a/b/c/../../../") == "/"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about some error cases? Like /a/b/c/../../../../
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The function has no error cases :) The function is supposed to be able to normalize every possible path.
/a/b/c/../../../../
will reduce to /
. I do have a test for that. In fact lots of tests - see normalizeCLIPathForVFS_path_beyond_root
below. I grouped them together not to have monster test cases spanning half of the file :)
|
||
// NOTE: If path to work dir contains symlinks (of then the case on macOS), boost might resolve | ||
// them, making the path different from tempDirPath. | ||
boost::filesystem::path expectedWorkDir = boost::filesystem::current_path().parent_path().parent_path().parent_path(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why parent 3 times?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because the working directory is set to tempDir.path() / "x/y/z"
and the paths I'm testing below sometimes go up a few levels so they do not always preserve the x/y/z
part. So I basically want tempDir.path()
but normalized the way a working directory would be (e.g. on MacOS the temp dir I get usually has a symlink in it that I need to resolve; on Windows it has a drive letter).
But I just realized that now it's no longer working dir so the name is a bit misleading so maybe that's what you meant. Renamed to expectedPrefix
.
44b33eb
to
f6fde4e
Compare
f6fde4e
to
b8e7786
Compare
Similar to #11544 (comment), I'm adding some refactors and small changes from work on #11688 as fixups (previous fixups squashed). Again, functionality did not change and almost all the changes were just in tests:
|
I'm closing this in favor of #11545. The only point of this PR was to be able to merge it without having to review all the dependencies first. Now that the dependencies are already merged, there's no point in keeping it around. I kept these PRs in sync at all times so if you already reviewed this, the only extra thing to review in #11545 is |
Fixes #4702.
Implements the
solc
part of #11408.solc-js
changes will be submitted in that repo.This is a version of #11545 that does not depend on the CLI refactor PRs (#11518, #11520, #11544) and does not include test cases for the CLI.
Things that were not implemented or were implemented differently than specified in the issue: