forked from lix-project/lix
Check 'follows' inputs
This commit is contained in:
parent
d15c20efd5
commit
7db879e65e
|
@ -469,12 +469,15 @@ LockedFlake lockFlake(
|
||||||
if (!updatesUsed.count(i))
|
if (!updatesUsed.count(i))
|
||||||
warn("the flag '--update-input %s' does not match any input", printInputPath(i));
|
warn("the flag '--update-input %s' does not match any input", printInputPath(i));
|
||||||
|
|
||||||
|
/* Check 'follows' inputs. */
|
||||||
|
newLockFile.check();
|
||||||
|
|
||||||
debug("new lock file: %s", newLockFile);
|
debug("new lock file: %s", newLockFile);
|
||||||
|
|
||||||
/* Check whether we need to / can write the new lock file. */
|
/* Check whether we need to / can write the new lock file. */
|
||||||
if (!(newLockFile == oldLockFile)) {
|
if (!(newLockFile == oldLockFile)) {
|
||||||
|
|
||||||
auto diff = diffLockFiles(oldLockFile, newLockFile);
|
auto diff = LockFile::diff(oldLockFile, newLockFile);
|
||||||
|
|
||||||
if (lockFlags.writeLockFile) {
|
if (lockFlags.writeLockFile) {
|
||||||
if (auto sourcePath = topRef.input.getSourcePath()) {
|
if (auto sourcePath = topRef.input.getSourcePath()) {
|
||||||
|
|
|
@ -238,21 +238,29 @@ InputPath parseInputPath(std::string_view s)
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void flattenLockFile(
|
std::map<InputPath, Node::Edge> LockFile::getAllInputs() const
|
||||||
std::shared_ptr<const Node> node,
|
|
||||||
const InputPath & prefix,
|
|
||||||
std::unordered_set<std::shared_ptr<const Node>> & done,
|
|
||||||
std::map<InputPath, Node::Edge> & res)
|
|
||||||
{
|
{
|
||||||
if (!done.insert(node).second) return;
|
std::unordered_set<std::shared_ptr<Node>> done;
|
||||||
|
std::map<InputPath, Node::Edge> res;
|
||||||
|
|
||||||
for (auto &[id, input] : node->inputs) {
|
std::function<void(const InputPath & prefix, std::shared_ptr<Node> node)> recurse;
|
||||||
auto inputPath(prefix);
|
|
||||||
inputPath.push_back(id);
|
recurse = [&](const InputPath & prefix, std::shared_ptr<Node> node)
|
||||||
res.emplace(inputPath, input);
|
{
|
||||||
if (auto child = std::get_if<0>(&input))
|
if (!done.insert(node).second) return;
|
||||||
flattenLockFile(*child, inputPath, done, res);
|
|
||||||
}
|
for (auto &[id, input] : node->inputs) {
|
||||||
|
auto inputPath(prefix);
|
||||||
|
inputPath.push_back(id);
|
||||||
|
res.emplace(inputPath, input);
|
||||||
|
if (auto child = std::get_if<0>(&input))
|
||||||
|
recurse(inputPath, *child);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
recurse({}, root);
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream & operator <<(std::ostream & stream, const Node::Edge & edge)
|
std::ostream & operator <<(std::ostream & stream, const Node::Edge & edge)
|
||||||
|
@ -275,13 +283,10 @@ static bool equals(const Node::Edge & e1, const Node::Edge & e2)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string diffLockFiles(const LockFile & oldLocks, const LockFile & newLocks)
|
std::string LockFile::diff(const LockFile & oldLocks, const LockFile & newLocks)
|
||||||
{
|
{
|
||||||
std::unordered_set<std::shared_ptr<const Node>> done;
|
auto oldFlat = oldLocks.getAllInputs();
|
||||||
std::map<InputPath, Node::Edge> oldFlat, newFlat;
|
auto newFlat = newLocks.getAllInputs();
|
||||||
flattenLockFile(oldLocks.root, {}, done, oldFlat);
|
|
||||||
done.clear();
|
|
||||||
flattenLockFile(newLocks.root, {}, done, newFlat);
|
|
||||||
|
|
||||||
auto i = oldFlat.begin();
|
auto i = oldFlat.begin();
|
||||||
auto j = newFlat.begin();
|
auto j = newFlat.begin();
|
||||||
|
@ -309,6 +314,22 @@ std::string diffLockFiles(const LockFile & oldLocks, const LockFile & newLocks)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LockFile::check()
|
||||||
|
{
|
||||||
|
auto inputs = getAllInputs();
|
||||||
|
|
||||||
|
for (auto & [inputPath, input] : inputs) {
|
||||||
|
if (auto follows = std::get_if<1>(&input)) {
|
||||||
|
if (!follows->empty() && !get(inputs, *follows))
|
||||||
|
throw Error("input '%s' follows a non-existent input '%s'",
|
||||||
|
printInputPath(inputPath),
|
||||||
|
printInputPath(*follows));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void check();
|
||||||
|
|
||||||
std::string printInputPath(const InputPath & path)
|
std::string printInputPath(const InputPath & path)
|
||||||
{
|
{
|
||||||
return concatStringsSep("/", path);
|
return concatStringsSep("/", path);
|
||||||
|
|
|
@ -67,6 +67,13 @@ struct LockFile
|
||||||
bool operator ==(const LockFile & other) const;
|
bool operator ==(const LockFile & other) const;
|
||||||
|
|
||||||
std::shared_ptr<Node> findInput(const InputPath & path);
|
std::shared_ptr<Node> findInput(const InputPath & path);
|
||||||
|
|
||||||
|
std::map<InputPath, Node::Edge> getAllInputs() const;
|
||||||
|
|
||||||
|
static std::string diff(const LockFile & oldLocks, const LockFile & newLocks);
|
||||||
|
|
||||||
|
/* Check that every 'follows' input target exists. */
|
||||||
|
void check();
|
||||||
};
|
};
|
||||||
|
|
||||||
std::ostream & operator <<(std::ostream & stream, const LockFile & lockFile);
|
std::ostream & operator <<(std::ostream & stream, const LockFile & lockFile);
|
||||||
|
@ -75,6 +82,4 @@ InputPath parseInputPath(std::string_view s);
|
||||||
|
|
||||||
std::string printInputPath(const InputPath & path);
|
std::string printInputPath(const InputPath & path);
|
||||||
|
|
||||||
std::string diffLockFiles(const LockFile & oldLocks, const LockFile & newLocks);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue