refactor(3p/nix/libexpr): Move EvalState:* implementations out of parser.y
Several definitions of functions declared in eval.hh were previously implemented in parser.y, this moves them over to parser.cc. While this still isn't a reasonable place to keep them, the long-term fix is more likely to be that eval.hh needs to be split up. Before we get to that point however, this already gives us the ability to use tooling with this code. Change-Id: If06fb655325fe281564047ffab0a0a640428a0ee Reviewed-on: https://cl.tvl.fyi/c/depot/+/1219 Tested-by: BuildkiteCI Reviewed-by: isomer <isomer@tvl.fyi>
This commit is contained in:
parent
5ae2a2b847
commit
e05eb20102
3 changed files with 156 additions and 150 deletions
140
third_party/nix/src/libexpr/parser.cc
vendored
140
third_party/nix/src/libexpr/parser.cc
vendored
|
@ -1,5 +1,14 @@
|
|||
#include "libexpr/parser.hh"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "libexpr/eval.hh"
|
||||
#include "libstore/download.hh"
|
||||
#include "libstore/store-api.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
void addAttr(ExprAttrs* attrs, AttrPath& attrPath, Expr* e, const Pos& pos) {
|
||||
|
@ -182,5 +191,136 @@ Expr* stripIndentation(const Pos& pos, SymbolTable& symbols,
|
|||
: new ExprConcatStrings(pos, true, es2);
|
||||
}
|
||||
|
||||
Path resolveExprPath(Path path) {
|
||||
assert(path[0] == '/');
|
||||
|
||||
/* If `path' is a symlink, follow it. This is so that relative
|
||||
path references work. */
|
||||
struct stat st;
|
||||
while (true) {
|
||||
if (lstat(path.c_str(), &st))
|
||||
throw SysError(format("getting status of '%1%'") % path);
|
||||
if (!S_ISLNK(st.st_mode)) {
|
||||
break;
|
||||
}
|
||||
path = absPath(readLink(path), dirOf(path));
|
||||
}
|
||||
|
||||
/* If `path' refers to a directory, append `/default.nix'. */
|
||||
if (S_ISDIR(st.st_mode)) path = canonPath(path + "/default.nix");
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
// These methods are actually declared in eval.hh, and were - for some
|
||||
// reason - previously implemented in parser.y.
|
||||
|
||||
Expr* EvalState::parseExprFromFile(const Path& path) {
|
||||
return parseExprFromFile(path, staticBaseEnv);
|
||||
}
|
||||
|
||||
Expr* EvalState::parseExprFromFile(const Path& path, StaticEnv& staticEnv) {
|
||||
return parse(readFile(path).c_str(), path, dirOf(path), staticEnv);
|
||||
}
|
||||
|
||||
Expr* EvalState::parseExprFromString(const std::string& s, const Path& basePath,
|
||||
StaticEnv& staticEnv) {
|
||||
return parse(s.c_str(), "(std::string)", basePath, staticEnv);
|
||||
}
|
||||
|
||||
Expr* EvalState::parseExprFromString(const std::string& s,
|
||||
const Path& basePath) {
|
||||
return parseExprFromString(s, basePath, staticBaseEnv);
|
||||
}
|
||||
|
||||
Expr* EvalState::parseStdin() {
|
||||
// Activity act(*logger, lvlTalkative, format("parsing standard input"));
|
||||
return parseExprFromString(drainFD(0), absPath("."));
|
||||
}
|
||||
|
||||
void EvalState::addToSearchPath(const std::string& s) {
|
||||
size_t pos = s.find('=');
|
||||
std::string prefix;
|
||||
Path path;
|
||||
if (pos == std::string::npos) {
|
||||
path = s;
|
||||
} else {
|
||||
prefix = std::string(s, 0, pos);
|
||||
path = std::string(s, pos + 1);
|
||||
}
|
||||
|
||||
searchPath.emplace_back(prefix, path);
|
||||
}
|
||||
|
||||
Path EvalState::findFile(const std::string& path) {
|
||||
return findFile(searchPath, path);
|
||||
}
|
||||
|
||||
Path EvalState::findFile(SearchPath& searchPath, const std::string& path,
|
||||
const Pos& pos) {
|
||||
for (auto& i : searchPath) {
|
||||
std::string suffix;
|
||||
if (i.first.empty())
|
||||
suffix = "/" + path;
|
||||
else {
|
||||
auto s = i.first.size();
|
||||
if (path.compare(0, s, i.first) != 0 ||
|
||||
(path.size() > s && path[s] != '/'))
|
||||
continue;
|
||||
suffix = path.size() == s ? "" : "/" + std::string(path, s);
|
||||
}
|
||||
auto r = resolveSearchPathElem(i);
|
||||
if (!r.first) {
|
||||
continue;
|
||||
}
|
||||
Path res = r.second + suffix;
|
||||
if (pathExists(res)) {
|
||||
return canonPath(res);
|
||||
}
|
||||
}
|
||||
format f = format(
|
||||
"file '%1%' was not found in the Nix search path (add it using $NIX_PATH "
|
||||
"or -I)" +
|
||||
std::string(pos ? ", at %2%" : ""));
|
||||
f.exceptions(boost::io::all_error_bits ^ boost::io::too_many_args_bit);
|
||||
throw ThrownError(f % path % pos);
|
||||
}
|
||||
|
||||
std::pair<bool, std::string> EvalState::resolveSearchPathElem(
|
||||
const SearchPathElem& elem) {
|
||||
auto i = searchPathResolved.find(elem.second);
|
||||
if (i != searchPathResolved.end()) {
|
||||
return i->second;
|
||||
}
|
||||
|
||||
std::pair<bool, std::string> res;
|
||||
|
||||
if (isUri(elem.second)) {
|
||||
try {
|
||||
CachedDownloadRequest request(elem.second);
|
||||
request.unpack = true;
|
||||
res = {true, getDownloader()->downloadCached(store, request).path};
|
||||
} catch (DownloadError& e) {
|
||||
LOG(WARNING) << "Nix search path entry '" << elem.second
|
||||
<< "' cannot be downloaded, ignoring";
|
||||
res = {false, ""};
|
||||
}
|
||||
} else {
|
||||
auto path = absPath(elem.second);
|
||||
if (pathExists(path)) {
|
||||
res = {true, path};
|
||||
} else {
|
||||
LOG(WARNING) << "Nix search path entry '" << elem.second
|
||||
<< "' does not exist, ignoring";
|
||||
res = {false, ""};
|
||||
}
|
||||
}
|
||||
|
||||
DLOG(INFO) << "resolved search path element '" << elem.second << "' to '"
|
||||
<< res.second << "'";
|
||||
|
||||
searchPathResolved[elem.second] = res;
|
||||
return res;
|
||||
}
|
||||
|
||||
} // namespace nix
|
||||
|
|
1
third_party/nix/src/libexpr/parser.hh
vendored
1
third_party/nix/src/libexpr/parser.hh
vendored
|
@ -53,5 +53,6 @@ void addFormal(const Pos& pos, Formals* formals, const Formal& formal);
|
|||
Expr* stripIndentation(const Pos& pos, SymbolTable& symbols,
|
||||
std::vector<Expr*>& es);
|
||||
|
||||
Path resolveExprPath(Path path);
|
||||
|
||||
} // namespace nix
|
||||
|
|
165
third_party/nix/src/libexpr/parser.y
vendored
165
third_party/nix/src/libexpr/parser.y
vendored
|
@ -325,165 +325,30 @@ formal
|
|||
#include <unistd.h>
|
||||
|
||||
#include "libexpr/eval.hh"
|
||||
#include "libstore/download.hh"
|
||||
#include "libstore/store-api.hh"
|
||||
|
||||
|
||||
namespace nix {
|
||||
|
||||
Expr* EvalState::parse(const char* text, const Path& path, const Path& basePath,
|
||||
StaticEnv& staticEnv) {
|
||||
yyscan_t scanner;
|
||||
ParseData data(*this);
|
||||
data.basePath = basePath;
|
||||
data.path = data.symbols.Create(path);
|
||||
|
||||
Expr * EvalState::parse(const char * text,
|
||||
const Path & path, const Path & basePath, StaticEnv & staticEnv)
|
||||
{
|
||||
yyscan_t scanner;
|
||||
ParseData data(*this);
|
||||
data.basePath = basePath;
|
||||
data.path = data.symbols.Create(path);
|
||||
yylex_init(&scanner);
|
||||
yy_scan_string(text, scanner);
|
||||
int res = yyparse(scanner, &data);
|
||||
yylex_destroy(scanner);
|
||||
|
||||
yylex_init(&scanner);
|
||||
yy_scan_string(text, scanner);
|
||||
int res = yyparse(scanner, &data);
|
||||
yylex_destroy(scanner);
|
||||
if (res) {
|
||||
throw ParseError(data.error);
|
||||
}
|
||||
|
||||
if (res) { throw ParseError(data.error); }
|
||||
data.result->bindVars(staticEnv);
|
||||
|
||||
data.result->bindVars(staticEnv);
|
||||
|
||||
return data.result;
|
||||
}
|
||||
|
||||
|
||||
Path resolveExprPath(Path path)
|
||||
{
|
||||
assert(path[0] == '/');
|
||||
|
||||
/* If `path' is a symlink, follow it. This is so that relative
|
||||
path references work. */
|
||||
struct stat st;
|
||||
while (true) {
|
||||
if (lstat(path.c_str(), &st))
|
||||
throw SysError(format("getting status of '%1%'") % path);
|
||||
if (!S_ISLNK(st.st_mode)) { break; }
|
||||
path = absPath(readLink(path), dirOf(path));
|
||||
}
|
||||
|
||||
/* If `path' refers to a directory, append `/default.nix'. */
|
||||
if (S_ISDIR(st.st_mode))
|
||||
path = canonPath(path + "/default.nix");
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
Expr * EvalState::parseExprFromFile(const Path & path)
|
||||
{
|
||||
return parseExprFromFile(path, staticBaseEnv);
|
||||
}
|
||||
|
||||
|
||||
Expr * EvalState::parseExprFromFile(const Path & path, StaticEnv & staticEnv)
|
||||
{
|
||||
return parse(readFile(path).c_str(), path, dirOf(path), staticEnv);
|
||||
}
|
||||
|
||||
|
||||
Expr * EvalState::parseExprFromString(const std::string & s, const Path & basePath, StaticEnv & staticEnv)
|
||||
{
|
||||
return parse(s.c_str(), "(std::string)", basePath, staticEnv);
|
||||
}
|
||||
|
||||
|
||||
Expr * EvalState::parseExprFromString(const std::string & s, const Path & basePath)
|
||||
{
|
||||
return parseExprFromString(s, basePath, staticBaseEnv);
|
||||
}
|
||||
|
||||
|
||||
Expr * EvalState::parseStdin()
|
||||
{
|
||||
//Activity act(*logger, lvlTalkative, format("parsing standard input"));
|
||||
return parseExprFromString(drainFD(0), absPath("."));
|
||||
}
|
||||
|
||||
|
||||
void EvalState::addToSearchPath(const std::string & s)
|
||||
{
|
||||
size_t pos = s.find('=');
|
||||
std::string prefix;
|
||||
Path path;
|
||||
if (pos == std::string::npos) {
|
||||
path = s;
|
||||
} else {
|
||||
prefix = std::string(s, 0, pos);
|
||||
path = std::string(s, pos + 1);
|
||||
}
|
||||
|
||||
searchPath.emplace_back(prefix, path);
|
||||
}
|
||||
|
||||
|
||||
Path EvalState::findFile(const std::string & path)
|
||||
{
|
||||
return findFile(searchPath, path);
|
||||
}
|
||||
|
||||
|
||||
Path EvalState::findFile(SearchPath & searchPath, const std::string & path, const Pos & pos)
|
||||
{
|
||||
for (auto & i : searchPath) {
|
||||
std::string suffix;
|
||||
if (i.first.empty())
|
||||
suffix = "/" + path;
|
||||
else {
|
||||
auto s = i.first.size();
|
||||
if (path.compare(0, s, i.first) != 0 ||
|
||||
(path.size() > s && path[s] != '/'))
|
||||
continue;
|
||||
suffix = path.size() == s ? "" : "/" + std::string(path, s);
|
||||
}
|
||||
auto r = resolveSearchPathElem(i);
|
||||
if (!r.first) { continue; }
|
||||
Path res = r.second + suffix;
|
||||
if (pathExists(res)) { return canonPath(res); }
|
||||
}
|
||||
format f = format(
|
||||
"file '%1%' was not found in the Nix search path (add it using $NIX_PATH or -I)"
|
||||
+ std::string(pos ? ", at %2%" : ""));
|
||||
f.exceptions(boost::io::all_error_bits ^ boost::io::too_many_args_bit);
|
||||
throw ThrownError(f % path % pos);
|
||||
}
|
||||
|
||||
|
||||
std::pair<bool, std::string> EvalState::resolveSearchPathElem(const SearchPathElem & elem)
|
||||
{
|
||||
auto i = searchPathResolved.find(elem.second);
|
||||
if (i != searchPathResolved.end()) { return i->second; }
|
||||
|
||||
std::pair<bool, std::string> res;
|
||||
|
||||
if (isUri(elem.second)) {
|
||||
try {
|
||||
CachedDownloadRequest request(elem.second);
|
||||
request.unpack = true;
|
||||
res = { true, getDownloader()->downloadCached(store, request).path };
|
||||
} catch (DownloadError & e) {
|
||||
LOG(WARNING) << "Nix search path entry '" << elem.second << "' cannot be downloaded, ignoring";
|
||||
res = { false, "" };
|
||||
}
|
||||
} else {
|
||||
auto path = absPath(elem.second);
|
||||
if (pathExists(path)) {
|
||||
res = { true, path };
|
||||
} else {
|
||||
LOG(WARNING) << "Nix search path entry '" << elem.second << "' does not exist, ignoring";
|
||||
res = { false, "" };
|
||||
}
|
||||
}
|
||||
|
||||
DLOG(INFO) << "resolved search path element '" << elem.second << "' to '" << res.second << "'";
|
||||
|
||||
searchPathResolved[elem.second] = res;
|
||||
return res;
|
||||
return data.result;
|
||||
}
|
||||
|
||||
} // namespace nix
|
||||
|
|
Loading…
Reference in a new issue