mirror of
https://github.com/NixOS/nix
synced 2025-06-24 22:11:15 +02:00
The ability to substitute inputs was removed in #10612 because it was broken: with user-specified inputs containing a `narHash` attribute, substitution resulted in an input that lacked the attributes returned by the real fetcher (such as `lastModified`). To fix this, we introduce a new input attribute `final`. If `final = true`, fetching the input cannot add or change any attributes. We only attempt to substitute inputs that have `final = true`. This is implied by lock file entries; we only write a lock file if all its entries are "final". The user can specified `final = true` in `fetchTree`, in which case it is their responsibility to ensure that all attributes returned by the fetcher are included in the `fetchTree` call. For example, nix eval --impure --expr 'builtins.fetchTree { type = "github"; owner = "NixOS"; repo = "patchelf"; final = true; narHash = "sha256-FSoxTcRZMGHNJh8dNtKOkcUtjhmhU6yQXcZZfUPLhQM="; }' succeeds in a store path with the specified NAR hash exists or is substitutable, but fails with error: fetching final input '{"final":true,"narHash":"sha256-FSoxTcRZMGHNJh8dNtKOkcUtjhmhU6yQXcZZfUPLhQM=","owner":"NixOS","repo":"patchelf","type":"github"}' resulted in different input '{"final":true,"lastModified":1718457448,"narHash":"sha256-FSoxTcRZMGHNJh8dNtKOkcUtjhmhU6yQXcZZfUPLhQM=","owner":"NixOS","repo":"patchelf","rev":"a0f54334df36770b335c051e540ba40afcbf8378","type":"github"}'
96 lines
2.1 KiB
C++
96 lines
2.1 KiB
C++
#pragma once
|
|
///@file
|
|
|
|
#include "flakeref.hh"
|
|
|
|
#include <nlohmann/json_fwd.hpp>
|
|
|
|
namespace nix {
|
|
class Store;
|
|
class StorePath;
|
|
}
|
|
|
|
namespace nix::flake {
|
|
|
|
typedef std::vector<FlakeId> InputPath;
|
|
|
|
struct LockedNode;
|
|
|
|
/**
|
|
* A node in the lock file. It has outgoing edges to other nodes (its
|
|
* inputs). Only the root node has this type; all other nodes have
|
|
* type LockedNode.
|
|
*/
|
|
struct Node : std::enable_shared_from_this<Node>
|
|
{
|
|
typedef std::variant<ref<LockedNode>, InputPath> Edge;
|
|
|
|
std::map<FlakeId, Edge> inputs;
|
|
|
|
virtual ~Node() { }
|
|
};
|
|
|
|
/**
|
|
* A non-root node in the lock file.
|
|
*/
|
|
struct LockedNode : Node
|
|
{
|
|
FlakeRef lockedRef, originalRef;
|
|
bool isFlake = true;
|
|
|
|
LockedNode(
|
|
const FlakeRef & lockedRef,
|
|
const FlakeRef & originalRef,
|
|
bool isFlake = true)
|
|
: lockedRef(lockedRef), originalRef(originalRef), isFlake(isFlake)
|
|
{ }
|
|
|
|
LockedNode(
|
|
const fetchers::Settings & fetchSettings,
|
|
const nlohmann::json & json);
|
|
|
|
StorePath computeStorePath(Store & store) const;
|
|
};
|
|
|
|
struct LockFile
|
|
{
|
|
ref<Node> root = make_ref<Node>();
|
|
|
|
LockFile() {};
|
|
LockFile(
|
|
const fetchers::Settings & fetchSettings,
|
|
std::string_view contents, std::string_view path);
|
|
|
|
typedef std::map<ref<const Node>, std::string> KeyMap;
|
|
|
|
std::pair<nlohmann::json, KeyMap> toJSON() const;
|
|
|
|
std::pair<std::string, KeyMap> to_string() const;
|
|
|
|
/**
|
|
* Check whether this lock file has any unlocked or non-final
|
|
* inputs. If so, return one.
|
|
*/
|
|
std::optional<FlakeRef> isUnlocked() const;
|
|
|
|
bool operator ==(const LockFile & other) const;
|
|
|
|
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);
|
|
|
|
InputPath parseInputPath(std::string_view s);
|
|
|
|
std::string printInputPath(const InputPath & path);
|
|
|
|
}
|