Skip to content

Commit

Permalink
Rename requires -> inputs, provides -> outputs
Browse files Browse the repository at this point in the history
Issue #2828.
  • Loading branch information
edolstra committed May 29, 2019
1 parent 49436bd commit 6e97998
Show file tree
Hide file tree
Showing 8 changed files with 112 additions and 111 deletions.
37 changes: 19 additions & 18 deletions doc/flakes/design.md
Expand Up @@ -103,12 +103,12 @@ module.
# A list of flake references denoting the flakes that this flake
# depends on. Nix will resolve and fetch these flakes and pass them
# as a function argument to `provides` below.
# as a function argument to `outputs` below.
#
# `flake:nixpkgs` denotes a flake named `nixpkgs` which is looked up
# in the flake registry, or in `flake.lock` inside this flake, if it
# exists.
requires = [ flake:nixpkgs ];
inputs = [ flake:nixpkgs ];
# The stuff provided by this flake. Flakes can provide whatever they
# want (convention over configuration), but some attributes have
Expand All @@ -117,9 +117,9 @@ module.
# `nixosModules` is used by NixOS to automatically pull in the
# modules provided by a flake.
#
# `provides` takes a single argument named `deps` that contains
# `outputs` takes a single argument named `deps` that contains
# the resolved set of flakes. (See below.)
provides = deps: {
outputs = deps: {
# This is searched by `nix`, so something like `nix install
# dwarffs.dwarffs` resolves to this `packages.dwarffs`.
Expand Down Expand Up @@ -168,7 +168,7 @@ Similarly, a minimal `flake.nix` for Nixpkgs:
description = "A collection of packages for the Nix package manager";
provides = deps:
outputs = deps:
let pkgs = import ./. {}; in
{
lib = import ./lib;
Expand Down Expand Up @@ -310,9 +310,9 @@ Example:
```


## `provides`
## `outputs`

The flake attribute `provides` is a function that takes an argument
The flake attribute `outputs` is a function that takes an argument
named `deps` and returns a (mostly) arbitrary attrset of values. Some
of the standard result attributes:

Expand All @@ -329,13 +329,13 @@ of the standard result attributes:
we need to avoid a situation where `nixos-rebuild` needs to fetch
its own `nixpkgs` just to do `evalModules`.)

* `shell`: A specification of a development environment in some TBD
* `devShell`: A specification of a development environment in some TBD
format.

The function argument `flakes` is an attrset that contains an
attribute for each dependency specified in `requires`. (Should it
attribute for each dependency specified in `inputs`. (Should it
contain transitive dependencies? Probably not.) Each attribute is an
attrset containing the `provides` of the dependency, in addition to
attrset containing the `outputs` of the dependency, in addition to
the following attributes:

* `path`: The path to the flake's source code. Useful when you want to
Expand Down Expand Up @@ -366,13 +366,13 @@ It may be useful to pull in repositories that are not flakes
(i.e. don't contain a `flake.nix`). This could be done in two ways:

* Allow flakes not to have a `flake.nix` file, in which case it's a
flake with no requires and no provides. The downside of this
flake with no inputs and no outputs. The downside of this
approach is that we can't detect accidental use of a non-flake
repository. (Also, we need to conjure up an identifier somehow.)

* Add a flake attribute to specifiy non-flake dependencies, e.g.

> nonFlakeRequires.foobar = github:foo/bar;
> nonFlakeInputs.foobar = github:foo/bar;

## Flake registry
Expand Down Expand Up @@ -454,7 +454,7 @@ The default installation source in `nix` is the `packages` from all
flakes in the registry, that is:
```
builtins.mapAttrs (flakeName: flakeInfo:
(getFlake flakeInfo.uri).${flakeName}.provides.packages or {})
(getFlake flakeInfo.uri).${flakeName}.outputs.packages or {})
builtins.flakeRegistry
```
(where `builtins.flakeRegistry` is the global registry with user
Expand All @@ -476,10 +476,11 @@ in the registry named `hello`.

Maybe the command

> nix shell
> nix dev-shell
should do something like use `provides.shell` to initialize the shell,
but probably we should ditch `nix shell` / `nix-shell` for direnv.
should do something like use `outputs.devShell` to initialize the
shell, but probably we should ditch `nix shell` / `nix-shell` for
direnv.


## Pure evaluation and caching
Expand Down Expand Up @@ -535,7 +536,7 @@ repositories.

```nix
{
provides = flakes: {
outputs = flakes: {
nixosSystems.default =
flakes.nixpkgs.lib.evalModules {
modules =
Expand All @@ -549,7 +550,7 @@ repositories.
};
};
requires =
inputs =
[ "nixpkgs/nixos-18.09"
"dwarffs"
"hydra"
Expand Down
8 changes: 4 additions & 4 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 5 additions & 5 deletions flake.nix
Expand Up @@ -5,13 +5,13 @@

epoch = 2019;

requires = [ "nixpkgs" ];
inputs = [ "nixpkgs" ];

provides = deps: rec {
outputs = inputs: rec {

hydraJobs = import ./release.nix {
nix = deps.self;
nixpkgs = deps.nixpkgs;
nix = inputs.self;
nixpkgs = inputs.nixpkgs;
};

checks = {
Expand All @@ -29,7 +29,7 @@
defaultPackage = packages.nix;

devShell = import ./shell.nix {
nixpkgs = deps.nixpkgs;
nixpkgs = inputs.nixpkgs;
};
};
}
90 changes: 45 additions & 45 deletions src/libexpr/primops/flake.cc
Expand Up @@ -56,21 +56,21 @@ LockFile::FlakeEntry readFlakeEntry(nlohmann::json json)
if (!flakeRef.isImmutable())
throw Error("cannot use mutable flake '%s' in pure mode", flakeRef);

LockFile::FlakeEntry entry(flakeRef, Hash((std::string) json["contentHash"]));
LockFile::FlakeEntry entry(flakeRef, Hash((std::string) json["narHash"]));

auto nonFlakeRequires = json["nonFlakeRequires"];
auto nonFlakeInputs = json["nonFlakeInputs"];

for (auto i = nonFlakeRequires.begin(); i != nonFlakeRequires.end(); ++i) {
for (auto i = nonFlakeInputs.begin(); i != nonFlakeInputs.end(); ++i) {
FlakeRef flakeRef(i->value("uri", ""));
if (!flakeRef.isImmutable())
throw Error("requested to fetch FlakeRef '%s' purely, which is mutable", flakeRef);
LockFile::NonFlakeEntry nonEntry(flakeRef, Hash(i->value("contentHash", "")));
LockFile::NonFlakeEntry nonEntry(flakeRef, Hash(i->value("narHash", "")));
entry.nonFlakeEntries.insert_or_assign(i.key(), nonEntry);
}

auto requires = json["requires"];
auto inputs = json["inputs"];

for (auto i = requires.begin(); i != requires.end(); ++i)
for (auto i = inputs.begin(); i != inputs.end(); ++i)
entry.flakeEntries.insert_or_assign(i.key(), readFlakeEntry(*i));

return entry;
Expand All @@ -89,19 +89,19 @@ LockFile readLockFile(const Path & path)
if (version != 1)
throw Error("lock file '%s' has unsupported version %d", path, version);

auto nonFlakeRequires = json["nonFlakeRequires"];
auto nonFlakeInputs = json["nonFlakeInputs"];

for (auto i = nonFlakeRequires.begin(); i != nonFlakeRequires.end(); ++i) {
for (auto i = nonFlakeInputs.begin(); i != nonFlakeInputs.end(); ++i) {
FlakeRef flakeRef(i->value("uri", ""));
LockFile::NonFlakeEntry nonEntry(flakeRef, Hash(i->value("contentHash", "")));
LockFile::NonFlakeEntry nonEntry(flakeRef, Hash(i->value("narHash", "")));
if (!flakeRef.isImmutable())
throw Error("found mutable FlakeRef '%s' in lockfile at path %s", flakeRef, path);
lockFile.nonFlakeEntries.insert_or_assign(i.key(), nonEntry);
}

auto requires = json["requires"];
auto inputs = json["inputs"];

for (auto i = requires.begin(); i != requires.end(); ++i)
for (auto i = inputs.begin(); i != inputs.end(); ++i)
lockFile.flakeEntries.insert_or_assign(i.key(), readFlakeEntry(*i));

return lockFile;
Expand All @@ -111,28 +111,28 @@ nlohmann::json flakeEntryToJson(const LockFile::FlakeEntry & entry)
{
nlohmann::json json;
json["uri"] = entry.ref.to_string();
json["contentHash"] = entry.narHash.to_string(SRI);
json["narHash"] = entry.narHash.to_string(SRI);
for (auto & x : entry.nonFlakeEntries) {
json["nonFlakeRequires"][x.first]["uri"] = x.second.ref.to_string();
json["nonFlakeRequires"][x.first]["contentHash"] = x.second.narHash.to_string(SRI);
json["nonFlakeInputs"][x.first]["uri"] = x.second.ref.to_string();
json["nonFlakeInputs"][x.first]["narHash"] = x.second.narHash.to_string(SRI);
}
for (auto & x : entry.flakeEntries)
json["requires"][x.first.to_string()] = flakeEntryToJson(x.second);
json["inputs"][x.first.to_string()] = flakeEntryToJson(x.second);
return json;
}

void writeLockFile(const LockFile & lockFile, const Path & path)
{
nlohmann::json json;
json["version"] = 1;
json["nonFlakeRequires"] = nlohmann::json::object();
json["nonFlakeInputs"] = nlohmann::json::object();
for (auto & x : lockFile.nonFlakeEntries) {
json["nonFlakeRequires"][x.first]["uri"] = x.second.ref.to_string();
json["nonFlakeRequires"][x.first]["contentHash"] = x.second.narHash.to_string(SRI);
json["nonFlakeInputs"][x.first]["uri"] = x.second.ref.to_string();
json["nonFlakeInputs"][x.first]["narHash"] = x.second.narHash.to_string(SRI);
}
json["requires"] = nlohmann::json::object();
json["inputs"] = nlohmann::json::object();
for (auto & x : lockFile.flakeEntries)
json["requires"][x.first.to_string()] = flakeEntryToJson(x.second);
json["inputs"][x.first.to_string()] = flakeEntryToJson(x.second);
createDirs(dirOf(path));
writeFile(path, json.dump(4) + "\n"); // '4' = indentation in json file
}
Expand Down Expand Up @@ -319,41 +319,41 @@ Flake getFlake(EvalState & state, const FlakeRef & flakeRef, bool impureIsAllowe
if (auto description = vInfo.attrs->get(state.sDescription))
flake.description = state.forceStringNoCtx(*(**description).value, *(**description).pos);

auto sRequires = state.symbols.create("requires");
auto sInputs = state.symbols.create("inputs");

if (auto requires = vInfo.attrs->get(sRequires)) {
state.forceList(*(**requires).value, *(**requires).pos);
for (unsigned int n = 0; n < (**requires).value->listSize(); ++n)
flake.requires.push_back(FlakeRef(state.forceStringNoCtx(
*(**requires).value->listElems()[n], *(**requires).pos)));
if (auto inputs = vInfo.attrs->get(sInputs)) {
state.forceList(*(**inputs).value, *(**inputs).pos);
for (unsigned int n = 0; n < (**inputs).value->listSize(); ++n)
flake.inputs.push_back(FlakeRef(state.forceStringNoCtx(
*(**inputs).value->listElems()[n], *(**inputs).pos)));
}

auto sNonFlakeRequires = state.symbols.create("nonFlakeRequires");
auto sNonFlakeInputs = state.symbols.create("nonFlakeInputs");

if (std::optional<Attr *> nonFlakeRequires = vInfo.attrs->get(sNonFlakeRequires)) {
state.forceAttrs(*(**nonFlakeRequires).value, *(**nonFlakeRequires).pos);
for (Attr attr : *(*(**nonFlakeRequires).value).attrs) {
if (std::optional<Attr *> nonFlakeInputs = vInfo.attrs->get(sNonFlakeInputs)) {
state.forceAttrs(*(**nonFlakeInputs).value, *(**nonFlakeInputs).pos);
for (Attr attr : *(*(**nonFlakeInputs).value).attrs) {
std::string myNonFlakeUri = state.forceStringNoCtx(*attr.value, *attr.pos);
FlakeRef nonFlakeRef = FlakeRef(myNonFlakeUri);
flake.nonFlakeRequires.insert_or_assign(attr.name, nonFlakeRef);
flake.nonFlakeInputs.insert_or_assign(attr.name, nonFlakeRef);
}
}

auto sProvides = state.symbols.create("provides");
auto sOutputs = state.symbols.create("outputs");

if (auto provides = vInfo.attrs->get(sProvides)) {
state.forceFunction(*(**provides).value, *(**provides).pos);
flake.vProvides = (**provides).value;
if (auto outputs = vInfo.attrs->get(sOutputs)) {
state.forceFunction(*(**outputs).value, *(**outputs).pos);
flake.vOutputs = (**outputs).value;
} else
throw Error("flake '%s' lacks attribute 'provides'", flakeRef);
throw Error("flake '%s' lacks attribute 'outputs'", flakeRef);

for (auto & attr : *vInfo.attrs) {
if (attr.name != sEpoch &&
attr.name != state.sName &&
attr.name != state.sDescription &&
attr.name != sRequires &&
attr.name != sNonFlakeRequires &&
attr.name != sProvides)
attr.name != sInputs &&
attr.name != sNonFlakeInputs &&
attr.name != sOutputs)
throw Error("flake '%s' has an unsupported attribute '%s', at %s",
flakeRef, attr.name, *attr.pos);
}
Expand Down Expand Up @@ -436,7 +436,7 @@ ResolvedFlake resolveFlakeFromLockFile(EvalState & state, const FlakeRef & flake

ResolvedFlake deps(flake);

for (auto & nonFlakeInfo : flake.nonFlakeRequires) {
for (auto & nonFlakeInfo : flake.nonFlakeInputs) {
FlakeRef ref = nonFlakeInfo.second;
auto i = lockFile.nonFlakeEntries.find(nonFlakeInfo.first);
if (i != lockFile.nonFlakeEntries.end()) {
Expand All @@ -451,7 +451,7 @@ ResolvedFlake resolveFlakeFromLockFile(EvalState & state, const FlakeRef & flake
}
}

for (auto newFlakeRef : flake.requires) {
for (auto newFlakeRef : flake.inputs) {
auto i = lockFile.flakeEntries.find(newFlakeRef);
if (i != lockFile.flakeEntries.end()) { // Propagate lockFile downwards if possible
ResolvedFlake newResFlake = resolveFlakeFromLockFile(state, i->second.ref, handleLockFile, entryToLockFile(i->second));
Expand Down Expand Up @@ -532,8 +532,8 @@ static void emitSourceInfoAttrs(EvalState & state, const SourceInfo & sourceInfo

void callFlake(EvalState & state, const ResolvedFlake & resFlake, Value & v)
{
// Construct the resulting attrset '{description, provides,
// ...}'. This attrset is passed lazily as an argument to 'provides'.
// Construct the resulting attrset '{description, outputs,
// ...}'. This attrset is passed lazily as an argument to 'outputs'.

state.mkAttrs(v, resFlake.flakeDeps.size() + resFlake.nonFlakeDeps.size() + 8);

Expand All @@ -558,8 +558,8 @@ void callFlake(EvalState & state, const ResolvedFlake & resFlake, Value & v)

emitSourceInfoAttrs(state, resFlake.flake.sourceInfo, v);

auto vProvides = state.allocAttr(v, state.symbols.create("provides"));
mkApp(*vProvides, *resFlake.flake.vProvides, v);
auto vOutputs = state.allocAttr(v, state.symbols.create("outputs"));
mkApp(*vOutputs, *resFlake.flake.vOutputs, v);

v.attrs->push_back(Attr(state.symbols.create("self"), &v));

Expand Down
6 changes: 3 additions & 3 deletions src/libexpr/primops/flake.hh
Expand Up @@ -106,9 +106,9 @@ struct Flake
FlakeRef originalRef;
std::string description;
SourceInfo sourceInfo;
std::vector<FlakeRef> requires;
std::map<FlakeAlias, FlakeRef> nonFlakeRequires;
Value * vProvides; // FIXME: gc
std::vector<FlakeRef> inputs;
std::map<FlakeAlias, FlakeRef> nonFlakeInputs;
Value * vOutputs; // FIXME: gc
unsigned int epoch;

Flake(const FlakeRef & origRef, const SourceInfo & sourceInfo)
Expand Down

0 comments on commit 6e97998

Please sign in to comment.