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

Stripping base path from CLI paths #11545

Merged
merged 3 commits into from
Aug 27, 2021
Merged

Conversation

cameel
Copy link
Member

@cameel cameel commented Jun 16, 2021

Fixes #4702.
Implements the solc part of #11408. solc-js changes will be submitted in that repo.
Depends on #11544. Merged.

This still work in progress. I'd say It's about 90% done. There's not much implementation left (it's very small overall) but some corner cases are not yet handled or not handled properly:

  • Paths with a different case on case-insensitive filesystems.
  • Paths starting with // (UNC paths).
  • Paths using .. to go beyond filesystem root (boost's normalization does not squash /../ into /).
  • Paths with symlinks.
  • Removing root name so that paths always start with / (rather than drive letter on Windows) when they're on the same partition as CWD.
  • Different behavior on some older Boost versions.

@cameel cameel self-assigned this Jun 16, 2021
@cameel cameel force-pushed the standard-json-cli-common-input-file-processing branch 4 times, most recently from 58efdde to cc6e5fc Compare June 17, 2021 17:11
@cameel cameel force-pushed the stripping-base-path-from-cli branch 5 times, most recently from 362d656 to 654dc3f Compare June 18, 2021 23:55
@cameel
Copy link
Member Author

cameel commented Jun 21, 2021

Here's a short update on the current status on this PR:

  • I dealt with most of the corner cases listed in PR description. The last remaining ones are:
    • Symlinks. On macOS in CI the path to the temporary directory contains a symlink (/var/folders/ -> /private/var/folders/) and Boost sometimes resolves the symlink when the path is relative and starts with ../. I suspect it might be a bug in its boost version but I need to investigate. This will be tedious because I can reproduce it only in CI.
    • The root path is sometimes C:/ on Windows where it should be normalized to /. This might be a bug on my part.
  • Base path docs need to be updated.
  • I resolved all the CI failures in the refactor PRs it depends on (CommandLineParser #11518, Local output streams in CommandLineParser #11520, Common input file processing for CLI and Standard JSON #11544). But as requested by @chriseth I'll put this one directly on develop anyway - in a stripped-down version (without CLI tests) - once I get tests to pass.

@cameel cameel force-pushed the stripping-base-path-from-cli branch from 2a89fdc to 52c5c9e Compare June 29, 2021 20:29
@cameel cameel force-pushed the standard-json-cli-common-input-file-processing branch 3 times, most recently from c2e67e1 to c1e4cb8 Compare July 1, 2021 18:23
@cameel cameel force-pushed the stripping-base-path-from-cli branch 5 times, most recently from b5820f0 to db0029b Compare July 2, 2021 18:35
@cameel cameel force-pushed the standard-json-cli-common-input-file-processing branch from c1e4cb8 to d85b750 Compare July 2, 2021 21:02
@cameel cameel force-pushed the stripping-base-path-from-cli branch 2 times, most recently from 7e9230d to 350a950 Compare July 5, 2021 19:02
@cameel cameel force-pushed the standard-json-cli-common-input-file-processing branch from d85b750 to 992c868 Compare July 5, 2021 19:06
@cameel cameel force-pushed the stripping-base-path-from-cli branch 2 times, most recently from 0763219 to 9cd715b Compare July 5, 2021 19:14
@cameel
Copy link
Member Author

cameel commented Jul 5, 2021

This PR is now working correctly on all platforms. It still depends on the CLI refactor so I have created an equivalent PR without the CLI tests that does not: #11617. These tests turned out to be crucial as I suspected though. There were tons of weird cases and the FileReader unit tests did not catch many of them (see #11617 (comment)).

@@ -31,9 +33,17 @@ using std::string;
namespace solidity::frontend
{

void FileReader::setBasePath(boost::filesystem::path const& _path)
{
m_basePath = (_path.empty() ? "" : normalizeCLIPathForVFS(_path));
Copy link
Member

@aarlt aarlt Aug 19, 2021

Choose a reason for hiding this comment

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

What about setting normalizeCLIPathForVFS(".") already here, if _path is empty? With this m_basePath would always contain a valid path.

Copy link
Member Author

Choose a reason for hiding this comment

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

The problem is that "" is a special case that is not equivalent to any specific path.

For example if I use the working dir as you're suggesting, it will break absolute paths - import "/x/y.sol" will try to load x.y.sol from work dir rather than the absolute /x/y.sol.

Using / would keep absolute paths working but it would relative paths - import "x/y.sol" would try to load /x.y.sol.

So these two values are out and I can't think of any other path that would keep --base-path="" working as it does now.

@cameel cameel force-pushed the stripping-base-path-from-cli branch from 444d863 to fa9576f Compare August 20, 2021 18:04
@cameel
Copy link
Member Author

cameel commented Aug 20, 2021

While working on #11409 I found a small bug introduced in this PR: standard input was not being handled correctly in combination with base path. <stdin> was converted to an absolute path as if it were a file name. I added a fixup that solves this and contains a test for this case.

I have also squashed the older fixups.

@@ -451,7 +451,7 @@ bool CommandLineInterface::readInputFiles()
m_standardJsonInput = readUntilEnd(m_sin);
Copy link
Member

Choose a reason for hiding this comment

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

Not related but this line seems to have its indentation off. Could you fix it since you're touching the file already?

Copy link
Member Author

Choose a reason for hiding this comment

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

Sure, but the indent on this line and others around it look fine to me (it's all tabs). Is this the right line?

Copy link
Member

Choose a reason for hiding this comment

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

Hm it looked weird on GitHub, not sure then.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, github renders tabs in a weird way - as if they were shifted left relative to the beginning of the line. Really annoying.

@@ -451,7 +451,7 @@ bool CommandLineInterface::readInputFiles()
m_standardJsonInput = readUntilEnd(m_sin);
}
else
m_fileReader.setSource(g_stdinFileName, readUntilEnd(m_sin));
m_fileReader.setStdin(readUntilEnd(m_sin));
Copy link
Member

Choose a reason for hiding this comment

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

Is this the only place we read from stdin?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah. This and the one 3 lines up. It used to be done separately for Standard JSON but I unified that in #11544 so that it's now done here for all input modes.


void FileReader::setStdin(SourceCode _source)
{
m_sourceCodes["<stdin>"] = std::move(_source);
Copy link
Member

Choose a reason for hiding this comment

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

Where do we use m_sourceCodes["<stdin>"]? I'm wondering if the key "<stdin>" can get misused/misplaced somewhere

Copy link
Member Author

Choose a reason for hiding this comment

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

It's passed along with all the other input files to the compiler stack. You can technically import it just like a normal file with import "<stdin>" because that's its source unit name. This is a pre-existing behavior documented in https://docs.soliditylang.org/en/latest/path-resolution.html#index-3.

It's possible to have a file that gets the same source unit name:

echo 'contract A {}' > '<stdin>'
echo 'contract B {}' | solc '<stdin>' - --base-path .

this line would then overwrite the content of that file in FileReader and replace it with the content of standard input. Not great but I think that <stdin> as a file name is obscure enough that it does not really matter all that much.

In any case this is how the compiler already worked before and my PR does not change that. I only added a dedicated function for adding content for this source unit name because setSource() now performs normalization and we obviously do not want that here.

Copy link
Member

Choose a reason for hiding this comment

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

Ok sounds good.

@cameel cameel force-pushed the stripping-base-path-from-cli branch from fa9576f to 37fed1e Compare August 26, 2021 18:24
@cameel
Copy link
Member Author

cameel commented Aug 26, 2021

I just pushed an updated version. It removes defaultCommandLineOptions() and has slightly reworded documentation (backported here from my new PR for --include-path).

@cameel cameel requested review from aarlt and leonardoalt August 26, 2021 18:28
@@ -103,6 +103,7 @@ set(libsolidity_sources
libsolidity/SyntaxTest.h
libsolidity/ViewPureChecker.cpp
libsolidity/analysis/FunctionCallGraph.cpp
libsolidity/interface/FileReader.cpp
Copy link
Member

Choose a reason for hiding this comment

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

What about libsolidity/interface/FileReader.h?

Copy link
Member Author

Choose a reason for hiding this comment

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

Boost tests typically do not have header files. Boost can find and run them without it.

The ones that do have headers here are actually a part of soltest/isoltest implementation and not test cases.

@cameel cameel force-pushed the stripping-base-path-from-cli branch from 37fed1e to 83a9983 Compare August 27, 2021 12:44
@cameel cameel requested a review from aarlt August 27, 2021 12:45
@cameel
Copy link
Member Author

cameel commented Aug 27, 2021

@aarlt Fixes applied. Ready for another round.

leonardoalt
leonardoalt previously approved these changes Aug 27, 2021
@cameel
Copy link
Member Author

cameel commented Aug 27, 2021

Thanks @leonardoalt! Could you reapprove? I just squashed the fixups.

@cameel cameel merged commit 5229ace into develop Aug 27, 2021
@cameel cameel deleted the stripping-base-path-from-cli branch August 27, 2021 14:06
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.

[CLI] Relative paths result in different contracts
4 participants