Merge pull request #9634 from 9999years/combine-abstract-pos-and-pos
Combine `AbstractPos`, `PosAdapter`, and `Pos`
(cherry picked from commit 113499d16fc87d53b73fb62fe6242154909756ed)
===
this is a bit cursed because originally it was based on InputAccessor
code that we don't have and moved/patched features we likewise don't
have (fetchToStore caching, all the individual accessors,
ContentAddressMethod). the commit is adjusted accordingly to
match (remove caching, ignore accessors, use FileIngestionMethod).
note that `state.rootPath . CanonPath == abs` and
computeStorePathForPath works relative to cwd, so the slight rewrite in
the moved fetchToStore is legal.
Change-Id: I05fd340c273f0bcc8ffabfebdc4a88b98083bce5
This commit is contained in:
parent
e9b5929b22
commit
89e99d94e4
|
@ -1,5 +1,6 @@
|
||||||
#include "util.hh"
|
#include "util.hh"
|
||||||
#include "editor-for.hh"
|
#include "editor-for.hh"
|
||||||
|
#include "source-path.hh"
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
///@file
|
///@file
|
||||||
|
|
||||||
#include "types.hh"
|
#include "types.hh"
|
||||||
#include "input-accessor.hh"
|
#include "source-path.hh"
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "installable-value.hh"
|
#include "installable-value.hh"
|
||||||
#include "eval-cache.hh"
|
#include "eval-cache.hh"
|
||||||
|
#include "fetch-to-store.hh"
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
|
@ -44,7 +45,7 @@ ref<InstallableValue> InstallableValue::require(ref<Installable> installable)
|
||||||
std::optional<DerivedPathWithInfo> InstallableValue::trySinglePathToDerivedPaths(Value & v, const PosIdx pos, std::string_view errorCtx)
|
std::optional<DerivedPathWithInfo> InstallableValue::trySinglePathToDerivedPaths(Value & v, const PosIdx pos, std::string_view errorCtx)
|
||||||
{
|
{
|
||||||
if (v.type() == nPath) {
|
if (v.type() == nPath) {
|
||||||
auto storePath = v.path().fetchToStore(state->store);
|
auto storePath = fetchToStore(*state->store, v.path());
|
||||||
return {{
|
return {{
|
||||||
.path = DerivedPath::Opaque {
|
.path = DerivedPath::Opaque {
|
||||||
.path = std::move(storePath),
|
.path = std::move(storePath),
|
||||||
|
|
|
@ -218,7 +218,7 @@ static std::ostream & showDebugTrace(std::ostream & out, const PosTable & positi
|
||||||
// prefer direct pos, but if noPos then try the expr.
|
// prefer direct pos, but if noPos then try the expr.
|
||||||
auto pos = dt.pos
|
auto pos = dt.pos
|
||||||
? dt.pos
|
? dt.pos
|
||||||
: static_cast<std::shared_ptr<AbstractPos>>(positions[dt.expr.getPos() ? dt.expr.getPos() : noPos]);
|
: positions[dt.expr.getPos() ? dt.expr.getPos() : noPos];
|
||||||
|
|
||||||
if (pos) {
|
if (pos) {
|
||||||
out << *pos;
|
out << *pos;
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "profiles.hh"
|
#include "profiles.hh"
|
||||||
#include "print.hh"
|
#include "print.hh"
|
||||||
#include "gc-small-vector.hh"
|
#include "gc-small-vector.hh"
|
||||||
|
#include "fetch-to-store.hh"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
@ -879,7 +880,7 @@ void EvalState::runDebugRepl(const Error * error, const Env & env, const Expr &
|
||||||
? std::make_unique<DebugTraceStacker>(
|
? std::make_unique<DebugTraceStacker>(
|
||||||
*this,
|
*this,
|
||||||
DebugTrace {
|
DebugTrace {
|
||||||
.pos = error->info().errPos ? error->info().errPos : static_cast<std::shared_ptr<AbstractPos>>(positions[expr.getPos()]),
|
.pos = error->info().errPos ? error->info().errPos : positions[expr.getPos()],
|
||||||
.expr = expr,
|
.expr = expr,
|
||||||
.env = env,
|
.env = env,
|
||||||
.hint = error->info().msg,
|
.hint = error->info().msg,
|
||||||
|
@ -916,7 +917,7 @@ static std::unique_ptr<DebugTraceStacker> makeDebugTraceStacker(
|
||||||
EvalState & state,
|
EvalState & state,
|
||||||
Expr & expr,
|
Expr & expr,
|
||||||
Env & env,
|
Env & env,
|
||||||
std::shared_ptr<AbstractPos> && pos,
|
std::shared_ptr<Pos> && pos,
|
||||||
const char * s,
|
const char * s,
|
||||||
const std::string & s2)
|
const std::string & s2)
|
||||||
{
|
{
|
||||||
|
@ -1214,7 +1215,7 @@ void EvalState::cacheFile(
|
||||||
*this,
|
*this,
|
||||||
*e,
|
*e,
|
||||||
this->baseEnv,
|
this->baseEnv,
|
||||||
e->getPos() ? static_cast<std::shared_ptr<AbstractPos>>(positions[e->getPos()]) : nullptr,
|
e->getPos() ? std::make_shared<Pos>(positions[e->getPos()]) : nullptr,
|
||||||
"while evaluating the file '%1%':", resolvedPath.to_string())
|
"while evaluating the file '%1%':", resolvedPath.to_string())
|
||||||
: nullptr;
|
: nullptr;
|
||||||
|
|
||||||
|
@ -2388,7 +2389,7 @@ StorePath EvalState::copyPathToStore(NixStringContext & context, const SourcePat
|
||||||
auto dstPath = i != srcToStore.end()
|
auto dstPath = i != srcToStore.end()
|
||||||
? i->second
|
? i->second
|
||||||
: [&]() {
|
: [&]() {
|
||||||
auto dstPath = path.fetchToStore(store, path.baseName(), nullptr, repair);
|
auto dstPath = fetchToStore(*store, path, path.baseName(), FileIngestionMethod::Recursive, nullptr, repair);
|
||||||
allowPath(dstPath);
|
allowPath(dstPath);
|
||||||
srcToStore.insert_or_assign(path, dstPath);
|
srcToStore.insert_or_assign(path, dstPath);
|
||||||
printMsg(lvlChatty, "copied source '%1%' -> '%2%'", path, store->printStorePath(dstPath));
|
printMsg(lvlChatty, "copied source '%1%' -> '%2%'", path, store->printStorePath(dstPath));
|
||||||
|
|
|
@ -141,7 +141,7 @@ struct RegexCache;
|
||||||
std::shared_ptr<RegexCache> makeRegexCache();
|
std::shared_ptr<RegexCache> makeRegexCache();
|
||||||
|
|
||||||
struct DebugTrace {
|
struct DebugTrace {
|
||||||
std::shared_ptr<AbstractPos> pos;
|
std::shared_ptr<Pos> pos;
|
||||||
const Expr & expr;
|
const Expr & expr;
|
||||||
const Env & env;
|
const Env & env;
|
||||||
hintformat hint;
|
hintformat hint;
|
||||||
|
|
|
@ -11,58 +11,6 @@ namespace nix {
|
||||||
|
|
||||||
ExprBlackHole eBlackHole;
|
ExprBlackHole eBlackHole;
|
||||||
|
|
||||||
struct PosAdapter : AbstractPos
|
|
||||||
{
|
|
||||||
Pos::Origin origin;
|
|
||||||
|
|
||||||
PosAdapter(Pos::Origin origin)
|
|
||||||
: origin(std::move(origin))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<std::string> getSource() const override
|
|
||||||
{
|
|
||||||
return std::visit(overloaded {
|
|
||||||
[](const Pos::none_tag &) -> std::optional<std::string> {
|
|
||||||
return std::nullopt;
|
|
||||||
},
|
|
||||||
[](const Pos::Stdin & s) -> std::optional<std::string> {
|
|
||||||
// Get rid of the null terminators added by the parser.
|
|
||||||
return std::string(s.source->c_str());
|
|
||||||
},
|
|
||||||
[](const Pos::String & s) -> std::optional<std::string> {
|
|
||||||
// Get rid of the null terminators added by the parser.
|
|
||||||
return std::string(s.source->c_str());
|
|
||||||
},
|
|
||||||
[](const SourcePath & path) -> std::optional<std::string> {
|
|
||||||
try {
|
|
||||||
return path.readFile();
|
|
||||||
} catch (Error &) {
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, origin);
|
|
||||||
}
|
|
||||||
|
|
||||||
void print(std::ostream & out) const override
|
|
||||||
{
|
|
||||||
std::visit(overloaded {
|
|
||||||
[&](const Pos::none_tag &) { out << "«none»"; },
|
|
||||||
[&](const Pos::Stdin &) { out << "«stdin»"; },
|
|
||||||
[&](const Pos::String & s) { out << "«string»"; },
|
|
||||||
[&](const SourcePath & path) { out << path; }
|
|
||||||
}, origin);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Pos::operator std::shared_ptr<AbstractPos>() const
|
|
||||||
{
|
|
||||||
auto pos = std::make_shared<PosAdapter>(origin);
|
|
||||||
pos->line = line;
|
|
||||||
pos->column = column;
|
|
||||||
return pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: remove, because *symbols* are abstract and do not have a single
|
// FIXME: remove, because *symbols* are abstract and do not have a single
|
||||||
// textual representation; see printIdentifier()
|
// textual representation; see printIdentifier()
|
||||||
std::ostream & operator <<(std::ostream & str, const SymbolStr & symbol)
|
std::ostream & operator <<(std::ostream & str, const SymbolStr & symbol)
|
||||||
|
@ -268,17 +216,6 @@ void ExprPos::show(const SymbolTable & symbols, std::ostream & str) const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::ostream & operator << (std::ostream & str, const Pos & pos)
|
|
||||||
{
|
|
||||||
if (auto pos2 = (std::shared_ptr<AbstractPos>) pos) {
|
|
||||||
str << *pos2;
|
|
||||||
} else
|
|
||||||
str << "undefined position";
|
|
||||||
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
std::string showAttrPath(const SymbolTable & symbols, const AttrPath & attrPath)
|
std::string showAttrPath(const SymbolTable & symbols, const AttrPath & attrPath)
|
||||||
{
|
{
|
||||||
std::ostringstream out;
|
std::ostringstream out;
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "symbol-table.hh"
|
#include "symbol-table.hh"
|
||||||
#include "error.hh"
|
#include "error.hh"
|
||||||
#include "chunked-vector.hh"
|
#include "chunked-vector.hh"
|
||||||
|
#include "position.hh"
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
|
@ -29,27 +30,6 @@ public:
|
||||||
using EvalError::EvalError;
|
using EvalError::EvalError;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Position objects.
|
|
||||||
*/
|
|
||||||
struct Pos
|
|
||||||
{
|
|
||||||
uint32_t line;
|
|
||||||
uint32_t column;
|
|
||||||
|
|
||||||
struct none_tag { };
|
|
||||||
struct Stdin { ref<std::string> source; };
|
|
||||||
struct String { ref<std::string> source; };
|
|
||||||
|
|
||||||
typedef std::variant<none_tag, Stdin, String, SourcePath> Origin;
|
|
||||||
|
|
||||||
Origin origin;
|
|
||||||
|
|
||||||
explicit operator bool() const { return line > 0; }
|
|
||||||
|
|
||||||
operator std::shared_ptr<AbstractPos>() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
class PosIdx {
|
class PosIdx {
|
||||||
friend class PosTable;
|
friend class PosTable;
|
||||||
|
|
||||||
|
@ -82,7 +62,7 @@ public:
|
||||||
mutable uint32_t idx = std::numeric_limits<uint32_t>::max();
|
mutable uint32_t idx = std::numeric_limits<uint32_t>::max();
|
||||||
|
|
||||||
// Used for searching in PosTable::[].
|
// Used for searching in PosTable::[].
|
||||||
explicit Origin(uint32_t idx): idx(idx), origin{Pos::none_tag()} {}
|
explicit Origin(uint32_t idx): idx(idx), origin{std::monostate()} {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
const Pos::Origin origin;
|
const Pos::Origin origin;
|
||||||
|
@ -133,8 +113,6 @@ public:
|
||||||
|
|
||||||
inline PosIdx noPos = {};
|
inline PosIdx noPos = {};
|
||||||
|
|
||||||
std::ostream & operator << (std::ostream & str, const Pos & pos);
|
|
||||||
|
|
||||||
|
|
||||||
struct Env;
|
struct Env;
|
||||||
struct Value;
|
struct Value;
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "value-to-json.hh"
|
#include "value-to-json.hh"
|
||||||
#include "value-to-xml.hh"
|
#include "value-to-xml.hh"
|
||||||
#include "primops.hh"
|
#include "primops.hh"
|
||||||
|
#include "fetch-to-store.hh"
|
||||||
|
|
||||||
#include <boost/container/small_vector.hpp>
|
#include <boost/container/small_vector.hpp>
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
|
@ -2235,9 +2236,8 @@ static void addPath(
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!expectedHash || !state.store->isValidPath(*expectedStorePath)) {
|
if (!expectedHash || !state.store->isValidPath(*expectedStorePath)) {
|
||||||
StorePath dstPath = settings.readOnlyMode
|
auto dstPath = fetchToStore(
|
||||||
? state.store->computeStorePathForPath(name, path, method, htSHA256, filter).first
|
*state.store, state.rootPath(CanonPath(path)), name, method, &filter, state.repair);
|
||||||
: state.store->addToStore(name, path, method, htSHA256, filter, state.repair, refs);
|
|
||||||
if (expectedHash && expectedStorePath != dstPath)
|
if (expectedHash && expectedStorePath != dstPath)
|
||||||
state.debugThrowLastTrace(Error("store path mismatch in (possibly filtered) path added from '%s'", path));
|
state.debugThrowLastTrace(Error("store path mismatch in (possibly filtered) path added from '%s'", path));
|
||||||
state.allowAndSetStorePathString(dstPath, v);
|
state.allowAndSetStorePathString(dstPath, v);
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "symbol-table.hh"
|
#include "symbol-table.hh"
|
||||||
#include "value/context.hh"
|
#include "value/context.hh"
|
||||||
#include "input-accessor.hh"
|
#include "input-accessor.hh"
|
||||||
|
#include "source-path.hh"
|
||||||
|
|
||||||
#if HAVE_BOEHMGC
|
#if HAVE_BOEHMGC
|
||||||
#include <gc/gc_allocator.h>
|
#include <gc/gc_allocator.h>
|
||||||
|
|
26
src/libfetchers/fetch-to-store.cc
Normal file
26
src/libfetchers/fetch-to-store.cc
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
#include "fetch-to-store.hh"
|
||||||
|
#include "fetchers.hh"
|
||||||
|
#include "cache.hh"
|
||||||
|
|
||||||
|
namespace nix {
|
||||||
|
|
||||||
|
StorePath fetchToStore(
|
||||||
|
Store & store,
|
||||||
|
const SourcePath & path,
|
||||||
|
std::string_view name,
|
||||||
|
FileIngestionMethod method,
|
||||||
|
PathFilter * filter,
|
||||||
|
RepairFlag repair)
|
||||||
|
{
|
||||||
|
Activity act(*logger, lvlChatty, actUnknown, fmt("copying '%s' to the store", path));
|
||||||
|
|
||||||
|
auto filter2 = filter ? *filter : defaultPathFilter;
|
||||||
|
|
||||||
|
return
|
||||||
|
settings.readOnlyMode
|
||||||
|
? store.computeStorePathForPath(name, path.path.abs(), method, htSHA256, filter2).first
|
||||||
|
: store.addToStore(name, path.path.abs(), method, htSHA256, filter2, repair);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
22
src/libfetchers/fetch-to-store.hh
Normal file
22
src/libfetchers/fetch-to-store.hh
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "source-path.hh"
|
||||||
|
#include "store-api.hh"
|
||||||
|
#include "util.hh"
|
||||||
|
#include "repair-flag.hh"
|
||||||
|
#include "content-address.hh"
|
||||||
|
|
||||||
|
namespace nix {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy the `path` to the Nix store.
|
||||||
|
*/
|
||||||
|
StorePath fetchToStore(
|
||||||
|
Store & store,
|
||||||
|
const SourcePath & path,
|
||||||
|
std::string_view name = "source",
|
||||||
|
FileIngestionMethod method = FileIngestionMethod::Recursive,
|
||||||
|
PathFilter * filter = nullptr,
|
||||||
|
RepairFlag repair = NoRepair);
|
||||||
|
|
||||||
|
}
|
|
@ -1,5 +1,7 @@
|
||||||
#include "fetchers.hh"
|
#include "fetchers.hh"
|
||||||
#include "store-api.hh"
|
#include "store-api.hh"
|
||||||
|
#include "source-path.hh"
|
||||||
|
#include "fetch-to-store.hh"
|
||||||
|
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "config.hh"
|
#include "config.hh"
|
||||||
#include "path-info.hh"
|
#include "path-info.hh"
|
||||||
#include "repair-flag.hh"
|
#include "repair-flag.hh"
|
||||||
|
#include "source-path.hh"
|
||||||
|
|
||||||
#include <nlohmann/json_fwd.hpp>
|
#include <nlohmann/json_fwd.hpp>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "error.hh"
|
#include "error.hh"
|
||||||
|
#include "position.hh"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
@ -9,7 +10,7 @@ namespace nix {
|
||||||
|
|
||||||
const std::string nativeSystem = SYSTEM;
|
const std::string nativeSystem = SYSTEM;
|
||||||
|
|
||||||
void BaseError::addTrace(std::shared_ptr<AbstractPos> && e, hintformat hint, bool frame)
|
void BaseError::addTrace(std::shared_ptr<Pos> && e, hintformat hint, bool frame)
|
||||||
{
|
{
|
||||||
err.traces.push_front(Trace { .pos = std::move(e), .hint = hint, .frame = frame });
|
err.traces.push_front(Trace { .pos = std::move(e), .hint = hint, .frame = frame });
|
||||||
}
|
}
|
||||||
|
@ -40,15 +41,6 @@ std::ostream & operator <<(std::ostream & os, const hintformat & hf)
|
||||||
return os << hf.str();
|
return os << hf.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream & operator <<(std::ostream & str, const AbstractPos & pos)
|
|
||||||
{
|
|
||||||
pos.print(str);
|
|
||||||
str << ":" << pos.line;
|
|
||||||
if (pos.column > 0)
|
|
||||||
str << ":" << pos.column;
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An arbitrarily defined value comparison for the purpose of using traces in the key of a sorted container.
|
* An arbitrarily defined value comparison for the purpose of using traces in the key of a sorted container.
|
||||||
*/
|
*/
|
||||||
|
@ -75,49 +67,10 @@ inline bool operator> (const Trace& lhs, const Trace& rhs) { return rhs < lhs; }
|
||||||
inline bool operator<=(const Trace& lhs, const Trace& rhs) { return !(lhs > rhs); }
|
inline bool operator<=(const Trace& lhs, const Trace& rhs) { return !(lhs > rhs); }
|
||||||
inline bool operator>=(const Trace& lhs, const Trace& rhs) { return !(lhs < rhs); }
|
inline bool operator>=(const Trace& lhs, const Trace& rhs) { return !(lhs < rhs); }
|
||||||
|
|
||||||
std::optional<LinesOfCode> AbstractPos::getCodeLines() const
|
|
||||||
{
|
|
||||||
if (line == 0)
|
|
||||||
return std::nullopt;
|
|
||||||
|
|
||||||
if (auto source = getSource()) {
|
|
||||||
|
|
||||||
std::istringstream iss(*source);
|
|
||||||
// count the newlines.
|
|
||||||
int count = 0;
|
|
||||||
std::string curLine;
|
|
||||||
int pl = line - 1;
|
|
||||||
|
|
||||||
LinesOfCode loc;
|
|
||||||
|
|
||||||
do {
|
|
||||||
std::getline(iss, curLine);
|
|
||||||
++count;
|
|
||||||
if (count < pl)
|
|
||||||
;
|
|
||||||
else if (count == pl) {
|
|
||||||
loc.prevLineOfCode = curLine;
|
|
||||||
} else if (count == pl + 1) {
|
|
||||||
loc.errLineOfCode = curLine;
|
|
||||||
} else if (count == pl + 2) {
|
|
||||||
loc.nextLineOfCode = curLine;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!iss.good())
|
|
||||||
break;
|
|
||||||
} while (true);
|
|
||||||
|
|
||||||
return loc;
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
// print lines of code to the ostream, indicating the error column.
|
// print lines of code to the ostream, indicating the error column.
|
||||||
void printCodeLines(std::ostream & out,
|
void printCodeLines(std::ostream & out,
|
||||||
const std::string & prefix,
|
const std::string & prefix,
|
||||||
const AbstractPos & errPos,
|
const Pos & errPos,
|
||||||
const LinesOfCode & loc)
|
const LinesOfCode & loc)
|
||||||
{
|
{
|
||||||
// previous line of code.
|
// previous line of code.
|
||||||
|
@ -195,7 +148,7 @@ static bool printUnknownLocations = getEnv("_NIX_DEVELOPER_SHOW_UNKNOWN_LOCATION
|
||||||
*
|
*
|
||||||
* @return true if a position was printed.
|
* @return true if a position was printed.
|
||||||
*/
|
*/
|
||||||
static bool printPosMaybe(std::ostream & oss, std::string_view indent, const std::shared_ptr<AbstractPos> & pos) {
|
static bool printPosMaybe(std::ostream & oss, std::string_view indent, const std::shared_ptr<Pos> & pos) {
|
||||||
bool hasPos = pos && *pos;
|
bool hasPos = pos && *pos;
|
||||||
if (hasPos) {
|
if (hasPos) {
|
||||||
oss << indent << ANSI_BLUE << "at " ANSI_WARNING << *pos << ANSI_NORMAL << ":";
|
oss << indent << ANSI_BLUE << "at " ANSI_WARNING << *pos << ANSI_NORMAL << ":";
|
||||||
|
|
|
@ -63,45 +63,15 @@ struct LinesOfCode {
|
||||||
std::optional<std::string> nextLineOfCode;
|
std::optional<std::string> nextLineOfCode;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
struct Pos;
|
||||||
* An abstract type that represents a location in a source file.
|
|
||||||
*/
|
|
||||||
struct AbstractPos
|
|
||||||
{
|
|
||||||
uint32_t line = 0;
|
|
||||||
uint32_t column = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An AbstractPos may be a "null object", representing an unknown position.
|
|
||||||
*
|
|
||||||
* Return true if this position is known.
|
|
||||||
*/
|
|
||||||
inline operator bool() const { return line != 0; };
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the contents of the source file.
|
|
||||||
*/
|
|
||||||
virtual std::optional<std::string> getSource() const
|
|
||||||
{ return std::nullopt; };
|
|
||||||
|
|
||||||
virtual void print(std::ostream & out) const = 0;
|
|
||||||
|
|
||||||
std::optional<LinesOfCode> getCodeLines() const;
|
|
||||||
|
|
||||||
virtual ~AbstractPos() = default;
|
|
||||||
|
|
||||||
inline auto operator<=>(const AbstractPos& rhs) const = default;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::ostream & operator << (std::ostream & str, const AbstractPos & pos);
|
|
||||||
|
|
||||||
void printCodeLines(std::ostream & out,
|
void printCodeLines(std::ostream & out,
|
||||||
const std::string & prefix,
|
const std::string & prefix,
|
||||||
const AbstractPos & errPos,
|
const Pos & errPos,
|
||||||
const LinesOfCode & loc);
|
const LinesOfCode & loc);
|
||||||
|
|
||||||
struct Trace {
|
struct Trace {
|
||||||
std::shared_ptr<AbstractPos> pos;
|
std::shared_ptr<Pos> pos;
|
||||||
hintformat hint;
|
hintformat hint;
|
||||||
bool frame;
|
bool frame;
|
||||||
};
|
};
|
||||||
|
@ -114,7 +84,7 @@ inline bool operator>=(const Trace& lhs, const Trace& rhs);
|
||||||
struct ErrorInfo {
|
struct ErrorInfo {
|
||||||
Verbosity level;
|
Verbosity level;
|
||||||
hintformat msg;
|
hintformat msg;
|
||||||
std::shared_ptr<AbstractPos> errPos;
|
std::shared_ptr<Pos> errPos;
|
||||||
std::list<Trace> traces;
|
std::list<Trace> traces;
|
||||||
|
|
||||||
Suggestions suggestions;
|
Suggestions suggestions;
|
||||||
|
@ -185,12 +155,12 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
void addTrace(std::shared_ptr<AbstractPos> && e, std::string_view fs, const Args & ... args)
|
void addTrace(std::shared_ptr<Pos> && e, std::string_view fs, const Args & ... args)
|
||||||
{
|
{
|
||||||
addTrace(std::move(e), hintfmt(std::string(fs), args...));
|
addTrace(std::move(e), hintfmt(std::string(fs), args...));
|
||||||
}
|
}
|
||||||
|
|
||||||
void addTrace(std::shared_ptr<AbstractPos> && e, hintformat hint, bool frame = false);
|
void addTrace(std::shared_ptr<Pos> && e, hintformat hint, bool frame = false);
|
||||||
|
|
||||||
bool hasTrace() const { return !err.traces.empty(); }
|
bool hasTrace() const { return !err.traces.empty(); }
|
||||||
|
|
||||||
|
|
35
src/libutil/input-accessor.hh
Normal file
35
src/libutil/input-accessor.hh
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
#pragma once
|
||||||
|
///@file
|
||||||
|
|
||||||
|
#include "types.hh"
|
||||||
|
#include "archive.hh"
|
||||||
|
|
||||||
|
namespace nix {
|
||||||
|
|
||||||
|
struct InputAccessor
|
||||||
|
{
|
||||||
|
enum Type {
|
||||||
|
tRegular, tSymlink, tDirectory,
|
||||||
|
/**
|
||||||
|
Any other node types that may be encountered on the file system, such as device nodes, sockets, named pipe, and possibly even more exotic things.
|
||||||
|
|
||||||
|
Responsible for `"unknown"` from `builtins.readFileType "/dev/null"`.
|
||||||
|
|
||||||
|
Unlike `DT_UNKNOWN`, this must not be used for deferring the lookup of types.
|
||||||
|
*/
|
||||||
|
tMisc
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Stat
|
||||||
|
{
|
||||||
|
Type type = tMisc;
|
||||||
|
//uint64_t fileSize = 0; // regular files only
|
||||||
|
bool isExecutable = false; // regular files only
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::optional<Type> DirEntry;
|
||||||
|
|
||||||
|
typedef std::map<std::string, DirEntry> DirEntries;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -1,6 +1,8 @@
|
||||||
#include "logging.hh"
|
#include "logging.hh"
|
||||||
#include "util.hh"
|
#include "util.hh"
|
||||||
#include "config.hh"
|
#include "config.hh"
|
||||||
|
#include "source-path.hh"
|
||||||
|
#include "position.hh"
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
|
@ -133,13 +135,13 @@ Activity::Activity(Logger & logger, Verbosity lvl, ActivityType type,
|
||||||
logger.startActivity(id, lvl, type, s, fields, parent);
|
logger.startActivity(id, lvl, type, s, fields, parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void to_json(nlohmann::json & json, std::shared_ptr<AbstractPos> pos)
|
void to_json(nlohmann::json & json, std::shared_ptr<Pos> pos)
|
||||||
{
|
{
|
||||||
if (pos) {
|
if (pos) {
|
||||||
json["line"] = pos->line;
|
json["line"] = pos->line;
|
||||||
json["column"] = pos->column;
|
json["column"] = pos->column;
|
||||||
std::ostringstream str;
|
std::ostringstream str;
|
||||||
pos->print(str);
|
pos->print(str, true);
|
||||||
json["file"] = str.str();
|
json["file"] = str.str();
|
||||||
} else {
|
} else {
|
||||||
json["line"] = nullptr;
|
json["line"] = nullptr;
|
||||||
|
|
112
src/libutil/position.cc
Normal file
112
src/libutil/position.cc
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
#include "position.hh"
|
||||||
|
|
||||||
|
namespace nix {
|
||||||
|
|
||||||
|
Pos::Pos(const Pos * other)
|
||||||
|
{
|
||||||
|
if (!other) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
line = other->line;
|
||||||
|
column = other->column;
|
||||||
|
origin = std::move(other->origin);
|
||||||
|
}
|
||||||
|
|
||||||
|
Pos::operator std::shared_ptr<Pos>() const
|
||||||
|
{
|
||||||
|
return std::make_shared<Pos>(&*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Pos::operator<(const Pos &rhs) const
|
||||||
|
{
|
||||||
|
return std::forward_as_tuple(line, column, origin)
|
||||||
|
< std::forward_as_tuple(rhs.line, rhs.column, rhs.origin);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<LinesOfCode> Pos::getCodeLines() const
|
||||||
|
{
|
||||||
|
if (line == 0)
|
||||||
|
return std::nullopt;
|
||||||
|
|
||||||
|
if (auto source = getSource()) {
|
||||||
|
|
||||||
|
std::istringstream iss(*source);
|
||||||
|
// count the newlines.
|
||||||
|
int count = 0;
|
||||||
|
std::string curLine;
|
||||||
|
int pl = line - 1;
|
||||||
|
|
||||||
|
LinesOfCode loc;
|
||||||
|
|
||||||
|
do {
|
||||||
|
std::getline(iss, curLine);
|
||||||
|
++count;
|
||||||
|
if (count < pl)
|
||||||
|
;
|
||||||
|
else if (count == pl) {
|
||||||
|
loc.prevLineOfCode = curLine;
|
||||||
|
} else if (count == pl + 1) {
|
||||||
|
loc.errLineOfCode = curLine;
|
||||||
|
} else if (count == pl + 2) {
|
||||||
|
loc.nextLineOfCode = curLine;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!iss.good())
|
||||||
|
break;
|
||||||
|
} while (true);
|
||||||
|
|
||||||
|
return loc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::optional<std::string> Pos::getSource() const
|
||||||
|
{
|
||||||
|
return std::visit(overloaded {
|
||||||
|
[](const std::monostate &) -> std::optional<std::string> {
|
||||||
|
return std::nullopt;
|
||||||
|
},
|
||||||
|
[](const Pos::Stdin & s) -> std::optional<std::string> {
|
||||||
|
// Get rid of the null terminators added by the parser.
|
||||||
|
return std::string(s.source->c_str());
|
||||||
|
},
|
||||||
|
[](const Pos::String & s) -> std::optional<std::string> {
|
||||||
|
// Get rid of the null terminators added by the parser.
|
||||||
|
return std::string(s.source->c_str());
|
||||||
|
},
|
||||||
|
[](const SourcePath & path) -> std::optional<std::string> {
|
||||||
|
try {
|
||||||
|
return path.readFile();
|
||||||
|
} catch (Error &) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, origin);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Pos::print(std::ostream & out, bool showOrigin) const
|
||||||
|
{
|
||||||
|
if (showOrigin) {
|
||||||
|
std::visit(overloaded {
|
||||||
|
[&](const std::monostate &) { out << "«none»"; },
|
||||||
|
[&](const Pos::Stdin &) { out << "«stdin»"; },
|
||||||
|
[&](const Pos::String & s) { out << "«string»"; },
|
||||||
|
[&](const SourcePath & path) { out << path; }
|
||||||
|
}, origin);
|
||||||
|
out << ":";
|
||||||
|
}
|
||||||
|
out << line;
|
||||||
|
if (column > 0)
|
||||||
|
out << ":" << column;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream & operator<<(std::ostream & str, const Pos & pos)
|
||||||
|
{
|
||||||
|
pos.print(str, true);
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
74
src/libutil/position.hh
Normal file
74
src/libutil/position.hh
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
#pragma once
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* @brief Pos and AbstractPos
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "source-path.hh"
|
||||||
|
|
||||||
|
namespace nix {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A position and an origin for that position (like a source file).
|
||||||
|
*/
|
||||||
|
struct Pos
|
||||||
|
{
|
||||||
|
uint32_t line = 0;
|
||||||
|
uint32_t column = 0;
|
||||||
|
|
||||||
|
struct Stdin {
|
||||||
|
ref<std::string> source;
|
||||||
|
bool operator==(const Stdin & rhs) const
|
||||||
|
{ return *source == *rhs.source; }
|
||||||
|
bool operator!=(const Stdin & rhs) const
|
||||||
|
{ return *source != *rhs.source; }
|
||||||
|
bool operator<(const Stdin & rhs) const
|
||||||
|
{ return *source < *rhs.source; }
|
||||||
|
};
|
||||||
|
struct String {
|
||||||
|
ref<std::string> source;
|
||||||
|
bool operator==(const String & rhs) const
|
||||||
|
{ return *source == *rhs.source; }
|
||||||
|
bool operator!=(const String & rhs) const
|
||||||
|
{ return *source != *rhs.source; }
|
||||||
|
bool operator<(const String & rhs) const
|
||||||
|
{ return *source < *rhs.source; }
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::variant<std::monostate, Stdin, String, SourcePath> Origin;
|
||||||
|
|
||||||
|
Origin origin = std::monostate();
|
||||||
|
|
||||||
|
Pos() { }
|
||||||
|
Pos(uint32_t line, uint32_t column, Origin origin)
|
||||||
|
: line(line), column(column), origin(origin) { }
|
||||||
|
Pos(Pos & other) = default;
|
||||||
|
Pos(const Pos & other) = default;
|
||||||
|
Pos(Pos && other) = default;
|
||||||
|
Pos(const Pos * other);
|
||||||
|
|
||||||
|
explicit operator bool() const { return line > 0; }
|
||||||
|
|
||||||
|
operator std::shared_ptr<Pos>() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the contents of the source file.
|
||||||
|
*/
|
||||||
|
std::optional<std::string> getSource() const;
|
||||||
|
|
||||||
|
void print(std::ostream & out, bool showOrigin) const;
|
||||||
|
|
||||||
|
std::optional<LinesOfCode> getCodeLines() const;
|
||||||
|
|
||||||
|
bool operator==(const Pos & rhs) const = default;
|
||||||
|
bool operator!=(const Pos & rhs) const = default;
|
||||||
|
bool operator<(const Pos & rhs) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::ostream & operator<<(std::ostream & str, const Pos & pos);
|
||||||
|
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
///@file
|
///@file
|
||||||
|
|
||||||
|
#include <compare>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#include "input-accessor.hh"
|
#include "source-path.hh"
|
||||||
#include "store-api.hh"
|
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
|
@ -57,18 +56,6 @@ InputAccessor::DirEntries SourcePath::readDirectory() const
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
StorePath SourcePath::fetchToStore(
|
|
||||||
ref<Store> store,
|
|
||||||
std::string_view name,
|
|
||||||
PathFilter * filter,
|
|
||||||
RepairFlag repair) const
|
|
||||||
{
|
|
||||||
return
|
|
||||||
settings.readOnlyMode
|
|
||||||
? store->computeStorePathForPath(name, path.abs(), FileIngestionMethod::Recursive, htSHA256, filter ? *filter : defaultPathFilter).first
|
|
||||||
: store->addToStore(name, path.abs(), FileIngestionMethod::Recursive, htSHA256, filter ? *filter : defaultPathFilter, repair);
|
|
||||||
}
|
|
||||||
|
|
||||||
SourcePath SourcePath::resolveSymlinks() const
|
SourcePath SourcePath::resolveSymlinks() const
|
||||||
{
|
{
|
||||||
SourcePath res(CanonPath::root);
|
SourcePath res(CanonPath::root);
|
|
@ -1,42 +1,17 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* @brief SourcePath
|
||||||
|
*/
|
||||||
|
|
||||||
#include "ref.hh"
|
#include "ref.hh"
|
||||||
#include "types.hh"
|
|
||||||
#include "archive.hh"
|
|
||||||
#include "canon-path.hh"
|
#include "canon-path.hh"
|
||||||
#include "repair-flag.hh"
|
#include "repair-flag.hh"
|
||||||
|
#include "input-accessor.hh"
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
class StorePath;
|
|
||||||
class Store;
|
|
||||||
|
|
||||||
struct InputAccessor
|
|
||||||
{
|
|
||||||
enum Type {
|
|
||||||
tRegular, tSymlink, tDirectory,
|
|
||||||
/**
|
|
||||||
Any other node types that may be encountered on the file system, such as device nodes, sockets, named pipe, and possibly even more exotic things.
|
|
||||||
|
|
||||||
Responsible for `"unknown"` from `builtins.readFileType "/dev/null"`.
|
|
||||||
|
|
||||||
Unlike `DT_UNKNOWN`, this must not be used for deferring the lookup of types.
|
|
||||||
*/
|
|
||||||
tMisc
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Stat
|
|
||||||
{
|
|
||||||
Type type = tMisc;
|
|
||||||
//uint64_t fileSize = 0; // regular files only
|
|
||||||
bool isExecutable = false; // regular files only
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef std::optional<Type> DirEntry;
|
|
||||||
|
|
||||||
typedef std::map<std::string, DirEntry> DirEntries;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An abstraction for accessing source files during
|
* An abstraction for accessing source files during
|
||||||
* evaluation. Currently, it's just a wrapper around `CanonPath` that
|
* evaluation. Currently, it's just a wrapper around `CanonPath` that
|
||||||
|
@ -106,15 +81,6 @@ struct SourcePath
|
||||||
PathFilter & filter = defaultPathFilter) const
|
PathFilter & filter = defaultPathFilter) const
|
||||||
{ return nix::dumpPath(path.abs(), sink, filter); }
|
{ return nix::dumpPath(path.abs(), sink, filter); }
|
||||||
|
|
||||||
/**
|
|
||||||
* Copy this `SourcePath` to the Nix store.
|
|
||||||
*/
|
|
||||||
StorePath fetchToStore(
|
|
||||||
ref<Store> store,
|
|
||||||
std::string_view name = "source",
|
|
||||||
PathFilter * filter = nullptr,
|
|
||||||
RepairFlag repair = NoRepair) const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the location of this path in the "real" filesystem, if
|
* Return the location of this path in the "real" filesystem, if
|
||||||
* it has a physical location.
|
* it has a physical location.
|
Loading…
Reference in a new issue