mirror of
https://github.com/NixOS/nix.git
synced 2025-12-23 01:11:07 +01:00
Subflakes are flakes in the same tree, accessed in flake inputs via
relative paths (e.g. `inputs.foo.url = "path:./subdir"`). Previously
these didn't work very well because they would be separately copied to
the store, which is inefficient and makes references to parent
directories tricky or impossible. Furthermore, they had their own NAR
hash in the lock file, which is superfluous since the parent is
already locked.
Now subflakes are accessed via the accessor of the calling flake. This
avoids the unnecessary copy and makes it possible for subflakes to
depend on flakes in a parent directory (so long as they're in the same
tree).
Lock file nodes for relative flake inputs now have a new `parent` field:
{
"locked": {
"path": "./subdir",
"type": "path"
},
"original": {
"path": "./subdir",
"type": "path"
},
"parent": [
"foo",
"bar"
]
}
which denotes that `./subdir` is to be interpreted relative to the
directory of the `bar` input of the `foo` input of the root flake.
Extracted from the lazy-trees branch.
103 lines
2.4 KiB
C++
103 lines
2.4 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;
|
|
|
|
/* The node relative to which relative source paths
|
|
(e.g. 'path:../foo') are interpreted. */
|
|
std::optional<InputPath> parentPath;
|
|
|
|
LockedNode(
|
|
const FlakeRef & lockedRef,
|
|
const FlakeRef & originalRef,
|
|
bool isFlake = true,
|
|
std::optional<InputPath> parentPath = {})
|
|
: lockedRef(lockedRef)
|
|
, originalRef(originalRef)
|
|
, isFlake(isFlake)
|
|
, parentPath(parentPath)
|
|
{ }
|
|
|
|
LockedNode(const nlohmann::json & json);
|
|
|
|
StorePath computeStorePath(Store & store) const;
|
|
};
|
|
|
|
struct LockFile
|
|
{
|
|
ref<Node> root = make_ref<Node>();
|
|
|
|
LockFile() {};
|
|
LockFile(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 inputs. If so,
|
|
* return one.
|
|
*/
|
|
std::optional<FlakeRef> isUnlocked() const;
|
|
|
|
bool operator ==(const LockFile & other) const;
|
|
// Needed for old gcc versions that don't synthesize it (like gcc 8.2.2
|
|
// that is still the default on aarch64-linux)
|
|
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);
|
|
|
|
}
|