mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #10199 from ethereum/readfile
[CLI] Improve error handling of missing/unwriteable files
This commit is contained in:
commit
eaba9a680a
@ -4,6 +4,8 @@ Language Features:
|
|||||||
* Ability to select the abi coder using ``pragma abicoder v1`` and ``pragma abicoder v2``.
|
* Ability to select the abi coder using ``pragma abicoder v1`` and ``pragma abicoder v2``.
|
||||||
|
|
||||||
Compiler Features:
|
Compiler Features:
|
||||||
|
* Command Line Interface: Report error if file could not be read in ``--standard-json`` mode.
|
||||||
|
* Command Line interface: Report proper error for each output file which could not be written. Previously an exception was thrown, and execution aborted, on the first error.
|
||||||
* SMTChecker: Add division by zero checks in the CHC engine.
|
* SMTChecker: Add division by zero checks in the CHC engine.
|
||||||
* SMTChecker: Support ``selector`` for expressions with value known at compile-time.
|
* SMTChecker: Support ``selector`` for expressions with value known at compile-time.
|
||||||
* Command Line Interface: New option ``--model-checker-timeout`` sets a timeout in milliseconds for each individual query performed by the SMTChecker.
|
* Command Line Interface: New option ``--model-checker-timeout`` sets a timeout in milliseconds for each individual query performed by the SMTChecker.
|
||||||
|
@ -47,8 +47,7 @@ inline T readFile(std::string const& _file)
|
|||||||
T ret;
|
T ret;
|
||||||
size_t const c_elementSize = sizeof(typename T::value_type);
|
size_t const c_elementSize = sizeof(typename T::value_type);
|
||||||
std::ifstream is(_file, std::ifstream::binary);
|
std::ifstream is(_file, std::ifstream::binary);
|
||||||
if (!is)
|
assertThrow(is, FileNotFound, _file);
|
||||||
return ret;
|
|
||||||
|
|
||||||
// get length of file:
|
// get length of file:
|
||||||
is.seekg(0, is.end);
|
is.seekg(0, is.end);
|
||||||
|
@ -32,7 +32,8 @@ namespace solidity::util
|
|||||||
{
|
{
|
||||||
|
|
||||||
/// Retrieve and returns the contents of the given file as a std::string.
|
/// Retrieve and returns the contents of the given file as a std::string.
|
||||||
/// If the file doesn't exist or isn't readable, returns an empty container / bytes.
|
/// If the file doesn't exist, it will throw a FileNotFound exception.
|
||||||
|
/// If the file is empty, returns an empty string.
|
||||||
std::string readFileAsString(std::string const& _file);
|
std::string readFileAsString(std::string const& _file);
|
||||||
|
|
||||||
/// Retrieve and returns the contents of standard input (until EOF).
|
/// Retrieve and returns the contents of standard input (until EOF).
|
||||||
|
@ -48,7 +48,7 @@ private:
|
|||||||
DEV_SIMPLE_EXCEPTION(InvalidAddress);
|
DEV_SIMPLE_EXCEPTION(InvalidAddress);
|
||||||
DEV_SIMPLE_EXCEPTION(BadHexCharacter);
|
DEV_SIMPLE_EXCEPTION(BadHexCharacter);
|
||||||
DEV_SIMPLE_EXCEPTION(BadHexCase);
|
DEV_SIMPLE_EXCEPTION(BadHexCase);
|
||||||
DEV_SIMPLE_EXCEPTION(FileError);
|
DEV_SIMPLE_EXCEPTION(FileNotFound);
|
||||||
DEV_SIMPLE_EXCEPTION(DataTooLong);
|
DEV_SIMPLE_EXCEPTION(DataTooLong);
|
||||||
DEV_SIMPLE_EXCEPTION(StringTooLong);
|
DEV_SIMPLE_EXCEPTION(StringTooLong);
|
||||||
|
|
||||||
|
@ -614,6 +614,7 @@ bool CommandLineInterface::readInputFilesAndConfigureRemappings()
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE: we ignore the FileNotFound exception as we manually check above
|
||||||
m_sourceCodes[infile.generic_string()] = readFileAsString(infile.string());
|
m_sourceCodes[infile.generic_string()] = readFileAsString(infile.string());
|
||||||
path = boost::filesystem::canonical(infile).string();
|
path = boost::filesystem::canonical(infile).string();
|
||||||
}
|
}
|
||||||
@ -643,6 +644,10 @@ bool CommandLineInterface::parseLibraryOption(string const& _input)
|
|||||||
{
|
{
|
||||||
// Thrown e.g. if path is too long.
|
// Thrown e.g. if path is too long.
|
||||||
}
|
}
|
||||||
|
catch (FileNotFound const&)
|
||||||
|
{
|
||||||
|
// Should not happen if `fs::is_regular_file` is correct.
|
||||||
|
}
|
||||||
|
|
||||||
vector<string> libraries;
|
vector<string> libraries;
|
||||||
boost::split(libraries, data, boost::is_space() || boost::is_any_of(","), boost::token_compress_on);
|
boost::split(libraries, data, boost::is_space() || boost::is_any_of(","), boost::token_compress_on);
|
||||||
@ -738,7 +743,11 @@ void CommandLineInterface::createFile(string const& _fileName, string const& _da
|
|||||||
ofstream outFile(pathName);
|
ofstream outFile(pathName);
|
||||||
outFile << _data;
|
outFile << _data;
|
||||||
if (!outFile)
|
if (!outFile)
|
||||||
BOOST_THROW_EXCEPTION(FileError() << errinfo_comment("Could not write to file: " + pathName));
|
{
|
||||||
|
serr() << "Could not write to file \"" << pathName << "\"." << endl;
|
||||||
|
m_error = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandLineInterface::createJson(string const& _fileName, string const& _json)
|
void CommandLineInterface::createJson(string const& _fileName, string const& _json)
|
||||||
@ -1146,6 +1155,7 @@ bool CommandLineInterface::processInput()
|
|||||||
if (!boost::filesystem::is_regular_file(canonicalPath))
|
if (!boost::filesystem::is_regular_file(canonicalPath))
|
||||||
return ReadCallback::Result{false, "Not a valid file."};
|
return ReadCallback::Result{false, "Not a valid file."};
|
||||||
|
|
||||||
|
// NOTE: we ignore the FileNotFound exception as we manually check above
|
||||||
auto contents = readFileAsString(canonicalPath.string());
|
auto contents = readFileAsString(canonicalPath.string());
|
||||||
m_sourceCodes[path.generic_string()] = contents;
|
m_sourceCodes[path.generic_string()] = contents;
|
||||||
return ReadCallback::Result{true, contents};
|
return ReadCallback::Result{true, contents};
|
||||||
@ -1232,7 +1242,17 @@ bool CommandLineInterface::processInput()
|
|||||||
if (jsonFile.empty())
|
if (jsonFile.empty())
|
||||||
input = readStandardInput();
|
input = readStandardInput();
|
||||||
else
|
else
|
||||||
input = readFileAsString(jsonFile);
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
input = readFileAsString(jsonFile);
|
||||||
|
}
|
||||||
|
catch (FileNotFound const&)
|
||||||
|
{
|
||||||
|
serr() << "File not found: " << jsonFile << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
StandardCompiler compiler(fileReader);
|
StandardCompiler compiler(fileReader);
|
||||||
sout() << compiler.compile(std::move(input)) << endl;
|
sout() << compiler.compile(std::move(input)) << endl;
|
||||||
return true;
|
return true;
|
||||||
|
1
test/cmdlineTests/standard_file_not_found/args
Normal file
1
test/cmdlineTests/standard_file_not_found/args
Normal file
@ -0,0 +1 @@
|
|||||||
|
--standard-json
|
1
test/cmdlineTests/standard_file_not_found/err
Normal file
1
test/cmdlineTests/standard_file_not_found/err
Normal file
@ -0,0 +1 @@
|
|||||||
|
File not found: standard_file_not_found/input.sol
|
1
test/cmdlineTests/standard_file_not_found/exit
Normal file
1
test/cmdlineTests/standard_file_not_found/exit
Normal file
@ -0,0 +1 @@
|
|||||||
|
1
|
@ -20,6 +20,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <libsolutil/CommonIO.h>
|
#include <libsolutil/CommonIO.h>
|
||||||
|
#include <libsolutil/Exceptions.h>
|
||||||
#include <liblangutil/ErrorReporter.h>
|
#include <liblangutil/ErrorReporter.h>
|
||||||
#include <liblangutil/Scanner.h>
|
#include <liblangutil/Scanner.h>
|
||||||
#include <libyul/AsmAnalysis.h>
|
#include <libyul/AsmAnalysis.h>
|
||||||
@ -243,8 +244,18 @@ Allowed options)",
|
|||||||
}
|
}
|
||||||
|
|
||||||
string input;
|
string input;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
input = readFileAsString(arguments["input-file"].as<string>());
|
||||||
|
}
|
||||||
|
catch (FileNotFound const& _exception)
|
||||||
|
{
|
||||||
|
cerr << "File not found:" << _exception.comment() << endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (arguments.count("input-file"))
|
if (arguments.count("input-file"))
|
||||||
YulOpti{}.runInteractive(readFileAsString(arguments["input-file"].as<string>()));
|
YulOpti{}.runInteractive(input);
|
||||||
else
|
else
|
||||||
cout << options;
|
cout << options;
|
||||||
|
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
|
|
||||||
#include <libsolutil/CommonIO.h>
|
#include <libsolutil/CommonIO.h>
|
||||||
#include <libsolutil/CommonData.h>
|
#include <libsolutil/CommonData.h>
|
||||||
|
#include <libsolutil/Exceptions.h>
|
||||||
|
|
||||||
#include <boost/program_options.hpp>
|
#include <boost/program_options.hpp>
|
||||||
|
|
||||||
@ -137,10 +138,19 @@ Allowed options)",
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
string input;
|
string input;
|
||||||
|
|
||||||
if (arguments.count("input-file"))
|
if (arguments.count("input-file"))
|
||||||
for (string path: arguments["input-file"].as<vector<string>>())
|
for (string path: arguments["input-file"].as<vector<string>>())
|
||||||
input += readFileAsString(path);
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
input += readFileAsString(path);
|
||||||
|
}
|
||||||
|
catch (FileNotFound const&)
|
||||||
|
{
|
||||||
|
cerr << "File not found: " << path << endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
input = readStandardInput();
|
input = readStandardInput();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user