2019-02-12 19:23:11 +02:00
|
|
|
#include "flake.hh"
|
2019-06-04 21:01:21 +03:00
|
|
|
#include "lockfile.hh"
|
2018-11-29 20:18:36 +02:00
|
|
|
#include "primops.hh"
|
|
|
|
#include "eval-inline.hh"
|
2020-01-21 17:27:53 +02:00
|
|
|
#include "store-api.hh"
|
2020-03-30 15:03:28 +03:00
|
|
|
#include "fetchers.hh"
|
2020-02-02 14:14:34 +02:00
|
|
|
#include "finally.hh"
|
2018-11-29 20:18:36 +02:00
|
|
|
|
|
|
|
namespace nix {
|
|
|
|
|
2019-05-29 16:31:07 +03:00
|
|
|
using namespace flake;
|
|
|
|
|
|
|
|
namespace flake {
|
|
|
|
|
2020-06-01 10:39:15 +03:00
|
|
|
typedef std::pair<Tree, FlakeRef> FetchedFlake;
|
|
|
|
typedef std::vector<std::pair<FlakeRef, FetchedFlake>> FlakeCache;
|
2019-09-19 00:59:45 +03:00
|
|
|
|
2020-06-01 10:39:15 +03:00
|
|
|
static std::optional<FetchedFlake> lookupInFlakeCache(
|
2020-01-29 22:10:27 +02:00
|
|
|
const FlakeCache & flakeCache,
|
2019-09-19 00:59:45 +03:00
|
|
|
const FlakeRef & flakeRef)
|
|
|
|
{
|
|
|
|
// FIXME: inefficient.
|
2020-01-29 22:10:27 +02:00
|
|
|
for (auto & i : flakeCache) {
|
|
|
|
if (flakeRef == i.first) {
|
2019-09-19 00:59:45 +03:00
|
|
|
debug("mapping '%s' to previously seen input '%s' -> '%s",
|
2020-06-01 10:39:15 +03:00
|
|
|
flakeRef, i.first, i.second.second);
|
2019-09-19 00:59:45 +03:00
|
|
|
return i.second;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-01 10:39:15 +03:00
|
|
|
return std::nullopt;
|
2019-09-19 00:59:45 +03:00
|
|
|
}
|
2019-06-21 20:04:58 +03:00
|
|
|
|
2020-04-06 15:56:13 +03:00
|
|
|
static std::tuple<fetchers::Tree, FlakeRef, FlakeRef> fetchOrSubstituteTree(
|
2020-02-02 13:41:23 +02:00
|
|
|
EvalState & state,
|
|
|
|
const FlakeRef & originalRef,
|
|
|
|
bool allowLookup,
|
|
|
|
FlakeCache & flakeCache)
|
|
|
|
{
|
2020-06-01 10:39:15 +03:00
|
|
|
auto fetched = lookupInFlakeCache(flakeCache, originalRef);
|
|
|
|
FlakeRef resolvedRef = originalRef;
|
2020-02-02 13:41:23 +02:00
|
|
|
|
2020-06-01 10:39:15 +03:00
|
|
|
if (!fetched) {
|
|
|
|
if (originalRef.input.isDirect()) {
|
|
|
|
fetched.emplace(originalRef.fetchTree(state.store));
|
|
|
|
} else {
|
|
|
|
if (allowLookup) {
|
|
|
|
resolvedRef = originalRef.resolve(state.store);
|
|
|
|
auto fetchedResolved = lookupInFlakeCache(flakeCache, originalRef);
|
|
|
|
if (!fetchedResolved) fetchedResolved.emplace(resolvedRef.fetchTree(state.store));
|
|
|
|
flakeCache.push_back({resolvedRef, fetchedResolved.value()});
|
|
|
|
fetched.emplace(fetchedResolved.value());
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
throw Error("'%s' is an indirect flake reference, but registry lookups are not allowed", originalRef);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
flakeCache.push_back({originalRef, fetched.value()});
|
|
|
|
}
|
2020-06-09 14:45:07 +03:00
|
|
|
|
2020-06-01 10:39:15 +03:00
|
|
|
auto [tree, lockedRef] = fetched.value();
|
2020-02-02 13:41:23 +02:00
|
|
|
|
|
|
|
debug("got tree '%s' from '%s'",
|
|
|
|
state.store->printStorePath(tree.storePath), lockedRef);
|
|
|
|
|
|
|
|
if (state.allowedPaths)
|
|
|
|
state.allowedPaths->insert(tree.actualPath);
|
|
|
|
|
Remove TreeInfo
The attributes previously stored in TreeInfo (narHash, revCount,
lastModified) are now stored in Input. This makes it less arbitrary
what attributes are stored where.
As a result, the lock file format has changed. An entry like
"info": {
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github"
},
is now stored as
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github",
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
The 'Input' class is now a dumb set of attributes. All the fetcher
implementations subclass InputScheme, not Input. This simplifies the
API.
Also, fix substitution of flake inputs. This was broken since lazy
flake fetching started using fetchTree internally.
2020-05-30 01:44:11 +03:00
|
|
|
assert(!originalRef.input.getNarHash() || tree.storePath == originalRef.input.computeStorePath(*state.store));
|
2020-02-02 13:41:23 +02:00
|
|
|
|
2020-04-06 15:56:13 +03:00
|
|
|
return {std::move(tree), resolvedRef, lockedRef};
|
2020-02-02 13:41:23 +02:00
|
|
|
}
|
|
|
|
|
2019-09-09 17:34:44 +03:00
|
|
|
static void expectType(EvalState & state, ValueType type,
|
|
|
|
Value & value, const Pos & pos)
|
|
|
|
{
|
2019-09-09 18:34:38 +03:00
|
|
|
if (value.type == tThunk && value.isTrivial())
|
2019-09-09 17:34:44 +03:00
|
|
|
state.forceValue(value, pos);
|
|
|
|
if (value.type != type)
|
|
|
|
throw Error("expected %s but got %s at %s",
|
|
|
|
showType(type), showType(value.type), pos);
|
|
|
|
}
|
|
|
|
|
Respect lock files of inputs + fine-grained lock file control
When computing a lock file, we now respect the lock files of flake
inputs. This is important for usability / reproducibility. For
example, the 'nixops' flake depends on the 'nixops-aws' and
'nixops-hetzner' repositories. So when the 'nixops' flake is used in
another flake, we want the versions of 'nixops-aws' and
'nixops-hetzner' locked by the the 'nixops' flake because those
presumably have been tested.
This can lead to a proliferation of versions of flakes like 'nixpkgs'
(since every flake's lock file could depend on a different version of
'nixpkgs'). This is not a major issue when using Nixpkgs overlays or
NixOS modules, since then the top-level flake composes those
overlays/modules into *its* version of Nixpkgs and all other versions
are ignored. Lock file computation has been made a bit more lazy so it
won't try to fetch all those versions of 'nixpkgs'.
However, in case it's necessary to minimize flake versions, there now
are two input attributes that allow this. First, you can copy an input
from another flake, as follows:
inputs.nixpkgs.follows = "dwarffs/nixpkgs";
This states that the calling flake's 'nixpkgs' input shall be the same
as the 'nixpkgs' input of the 'dwarffs' input.
Second, you can override inputs of inputs:
inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
inputs.nixops.inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
or equivalently, using 'follows':
inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
inputs.nixops.inputs.nixpkgs.follows = "nixpkgs";
This states that the 'nixpkgs' input of the 'nixops' input shall be
the same as the calling flake's 'nixpkgs' input.
Finally, at '-v' Nix now prints the changes to the lock file, e.g.
$ nix flake update ~/Misc/eelco-configurations/hagbard
inputs of flake 'git+file:///home/eelco/Misc/eelco-configurations?subdir=hagbard' changed:
updated 'nixpkgs': 'github:edolstra/nixpkgs/7845bf5f4b3013df1cf036e9c9c3a55a30331db9' -> 'github:edolstra/nixpkgs/03f3def66a104a221aac8b751eeb7075374848fd'
removed 'nixops'
removed 'nixops/nixops-aws'
removed 'nixops/nixops-hetzner'
removed 'nixops/nixpkgs'
2020-01-24 23:05:11 +02:00
|
|
|
static std::map<FlakeId, FlakeInput> parseFlakeInputs(
|
|
|
|
EvalState & state, Value * value, const Pos & pos);
|
|
|
|
|
|
|
|
static FlakeInput parseFlakeInput(EvalState & state,
|
|
|
|
const std::string & inputName, Value * value, const Pos & pos)
|
|
|
|
{
|
|
|
|
expectType(state, tAttrs, *value, pos);
|
|
|
|
|
2020-06-11 15:40:21 +03:00
|
|
|
FlakeInput input;
|
Respect lock files of inputs + fine-grained lock file control
When computing a lock file, we now respect the lock files of flake
inputs. This is important for usability / reproducibility. For
example, the 'nixops' flake depends on the 'nixops-aws' and
'nixops-hetzner' repositories. So when the 'nixops' flake is used in
another flake, we want the versions of 'nixops-aws' and
'nixops-hetzner' locked by the the 'nixops' flake because those
presumably have been tested.
This can lead to a proliferation of versions of flakes like 'nixpkgs'
(since every flake's lock file could depend on a different version of
'nixpkgs'). This is not a major issue when using Nixpkgs overlays or
NixOS modules, since then the top-level flake composes those
overlays/modules into *its* version of Nixpkgs and all other versions
are ignored. Lock file computation has been made a bit more lazy so it
won't try to fetch all those versions of 'nixpkgs'.
However, in case it's necessary to minimize flake versions, there now
are two input attributes that allow this. First, you can copy an input
from another flake, as follows:
inputs.nixpkgs.follows = "dwarffs/nixpkgs";
This states that the calling flake's 'nixpkgs' input shall be the same
as the 'nixpkgs' input of the 'dwarffs' input.
Second, you can override inputs of inputs:
inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
inputs.nixops.inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
or equivalently, using 'follows':
inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
inputs.nixops.inputs.nixpkgs.follows = "nixpkgs";
This states that the 'nixpkgs' input of the 'nixops' input shall be
the same as the calling flake's 'nixpkgs' input.
Finally, at '-v' Nix now prints the changes to the lock file, e.g.
$ nix flake update ~/Misc/eelco-configurations/hagbard
inputs of flake 'git+file:///home/eelco/Misc/eelco-configurations?subdir=hagbard' changed:
updated 'nixpkgs': 'github:edolstra/nixpkgs/7845bf5f4b3013df1cf036e9c9c3a55a30331db9' -> 'github:edolstra/nixpkgs/03f3def66a104a221aac8b751eeb7075374848fd'
removed 'nixops'
removed 'nixops/nixops-aws'
removed 'nixops/nixops-hetzner'
removed 'nixops/nixpkgs'
2020-01-24 23:05:11 +02:00
|
|
|
|
|
|
|
auto sInputs = state.symbols.create("inputs");
|
|
|
|
auto sUrl = state.symbols.create("url");
|
|
|
|
auto sFlake = state.symbols.create("flake");
|
|
|
|
auto sFollows = state.symbols.create("follows");
|
|
|
|
|
2020-03-17 21:54:36 +02:00
|
|
|
fetchers::Attrs attrs;
|
2020-01-31 21:50:46 +02:00
|
|
|
std::optional<std::string> url;
|
|
|
|
|
2020-03-17 21:54:36 +02:00
|
|
|
for (nix::Attr attr : *(value->attrs)) {
|
2020-01-31 21:50:46 +02:00
|
|
|
try {
|
2020-05-06 18:48:18 +03:00
|
|
|
if (attr.name == sUrl) {
|
2020-01-31 21:50:46 +02:00
|
|
|
expectType(state, tString, *attr.value, *attr.pos);
|
|
|
|
url = attr.value->string.s;
|
|
|
|
attrs.emplace("url", *url);
|
|
|
|
} else if (attr.name == sFlake) {
|
|
|
|
expectType(state, tBool, *attr.value, *attr.pos);
|
|
|
|
input.isFlake = attr.value->boolean;
|
|
|
|
} else if (attr.name == sInputs) {
|
|
|
|
input.overrides = parseFlakeInputs(state, attr.value, *attr.pos);
|
|
|
|
} else if (attr.name == sFollows) {
|
|
|
|
expectType(state, tString, *attr.value, *attr.pos);
|
2020-01-29 15:57:57 +02:00
|
|
|
input.follows = parseInputPath(attr.value->string.s);
|
2020-01-31 21:50:46 +02:00
|
|
|
} else {
|
|
|
|
state.forceValue(*attr.value);
|
|
|
|
if (attr.value->type == tString)
|
|
|
|
attrs.emplace(attr.name, attr.value->string.s);
|
|
|
|
else
|
2020-03-09 16:28:41 +02:00
|
|
|
throw TypeError("flake input attribute '%s' is %s while a string is expected",
|
|
|
|
attr.name, showType(*attr.value));
|
2020-01-29 15:57:57 +02:00
|
|
|
}
|
2020-01-31 21:50:46 +02:00
|
|
|
} catch (Error & e) {
|
2020-07-06 17:40:10 +03:00
|
|
|
e.addTrace(*attr.pos, hintfmt("in flake attribute '%s'", attr.name));
|
2020-01-31 21:50:46 +02:00
|
|
|
throw;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (attrs.count("type"))
|
|
|
|
try {
|
|
|
|
input.ref = FlakeRef::fromAttrs(attrs);
|
|
|
|
} catch (Error & e) {
|
2020-07-06 17:40:10 +03:00
|
|
|
e.addTrace(pos, hintfmt("in flake input"));
|
2020-01-31 21:50:46 +02:00
|
|
|
throw;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
attrs.erase("url");
|
|
|
|
if (!attrs.empty())
|
|
|
|
throw Error("unexpected flake input attribute '%s', at %s", attrs.begin()->first, pos);
|
|
|
|
if (url)
|
2020-04-27 23:53:11 +03:00
|
|
|
input.ref = parseFlakeRef(*url, {}, true);
|
Respect lock files of inputs + fine-grained lock file control
When computing a lock file, we now respect the lock files of flake
inputs. This is important for usability / reproducibility. For
example, the 'nixops' flake depends on the 'nixops-aws' and
'nixops-hetzner' repositories. So when the 'nixops' flake is used in
another flake, we want the versions of 'nixops-aws' and
'nixops-hetzner' locked by the the 'nixops' flake because those
presumably have been tested.
This can lead to a proliferation of versions of flakes like 'nixpkgs'
(since every flake's lock file could depend on a different version of
'nixpkgs'). This is not a major issue when using Nixpkgs overlays or
NixOS modules, since then the top-level flake composes those
overlays/modules into *its* version of Nixpkgs and all other versions
are ignored. Lock file computation has been made a bit more lazy so it
won't try to fetch all those versions of 'nixpkgs'.
However, in case it's necessary to minimize flake versions, there now
are two input attributes that allow this. First, you can copy an input
from another flake, as follows:
inputs.nixpkgs.follows = "dwarffs/nixpkgs";
This states that the calling flake's 'nixpkgs' input shall be the same
as the 'nixpkgs' input of the 'dwarffs' input.
Second, you can override inputs of inputs:
inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
inputs.nixops.inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
or equivalently, using 'follows':
inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
inputs.nixops.inputs.nixpkgs.follows = "nixpkgs";
This states that the 'nixpkgs' input of the 'nixops' input shall be
the same as the calling flake's 'nixpkgs' input.
Finally, at '-v' Nix now prints the changes to the lock file, e.g.
$ nix flake update ~/Misc/eelco-configurations/hagbard
inputs of flake 'git+file:///home/eelco/Misc/eelco-configurations?subdir=hagbard' changed:
updated 'nixpkgs': 'github:edolstra/nixpkgs/7845bf5f4b3013df1cf036e9c9c3a55a30331db9' -> 'github:edolstra/nixpkgs/03f3def66a104a221aac8b751eeb7075374848fd'
removed 'nixops'
removed 'nixops/nixops-aws'
removed 'nixops/nixops-hetzner'
removed 'nixops/nixpkgs'
2020-01-24 23:05:11 +02:00
|
|
|
}
|
|
|
|
|
2020-06-11 15:40:21 +03:00
|
|
|
if (!input.follows && !input.ref)
|
|
|
|
input.ref = FlakeRef::fromAttrs({{"type", "indirect"}, {"id", inputName}});
|
|
|
|
|
Respect lock files of inputs + fine-grained lock file control
When computing a lock file, we now respect the lock files of flake
inputs. This is important for usability / reproducibility. For
example, the 'nixops' flake depends on the 'nixops-aws' and
'nixops-hetzner' repositories. So when the 'nixops' flake is used in
another flake, we want the versions of 'nixops-aws' and
'nixops-hetzner' locked by the the 'nixops' flake because those
presumably have been tested.
This can lead to a proliferation of versions of flakes like 'nixpkgs'
(since every flake's lock file could depend on a different version of
'nixpkgs'). This is not a major issue when using Nixpkgs overlays or
NixOS modules, since then the top-level flake composes those
overlays/modules into *its* version of Nixpkgs and all other versions
are ignored. Lock file computation has been made a bit more lazy so it
won't try to fetch all those versions of 'nixpkgs'.
However, in case it's necessary to minimize flake versions, there now
are two input attributes that allow this. First, you can copy an input
from another flake, as follows:
inputs.nixpkgs.follows = "dwarffs/nixpkgs";
This states that the calling flake's 'nixpkgs' input shall be the same
as the 'nixpkgs' input of the 'dwarffs' input.
Second, you can override inputs of inputs:
inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
inputs.nixops.inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
or equivalently, using 'follows':
inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
inputs.nixops.inputs.nixpkgs.follows = "nixpkgs";
This states that the 'nixpkgs' input of the 'nixops' input shall be
the same as the calling flake's 'nixpkgs' input.
Finally, at '-v' Nix now prints the changes to the lock file, e.g.
$ nix flake update ~/Misc/eelco-configurations/hagbard
inputs of flake 'git+file:///home/eelco/Misc/eelco-configurations?subdir=hagbard' changed:
updated 'nixpkgs': 'github:edolstra/nixpkgs/7845bf5f4b3013df1cf036e9c9c3a55a30331db9' -> 'github:edolstra/nixpkgs/03f3def66a104a221aac8b751eeb7075374848fd'
removed 'nixops'
removed 'nixops/nixops-aws'
removed 'nixops/nixops-hetzner'
removed 'nixops/nixpkgs'
2020-01-24 23:05:11 +02:00
|
|
|
return input;
|
|
|
|
}
|
|
|
|
|
|
|
|
static std::map<FlakeId, FlakeInput> parseFlakeInputs(
|
|
|
|
EvalState & state, Value * value, const Pos & pos)
|
|
|
|
{
|
|
|
|
std::map<FlakeId, FlakeInput> inputs;
|
|
|
|
|
|
|
|
expectType(state, tAttrs, *value, pos);
|
|
|
|
|
2020-03-17 21:54:36 +02:00
|
|
|
for (nix::Attr & inputAttr : *(*value).attrs) {
|
Respect lock files of inputs + fine-grained lock file control
When computing a lock file, we now respect the lock files of flake
inputs. This is important for usability / reproducibility. For
example, the 'nixops' flake depends on the 'nixops-aws' and
'nixops-hetzner' repositories. So when the 'nixops' flake is used in
another flake, we want the versions of 'nixops-aws' and
'nixops-hetzner' locked by the the 'nixops' flake because those
presumably have been tested.
This can lead to a proliferation of versions of flakes like 'nixpkgs'
(since every flake's lock file could depend on a different version of
'nixpkgs'). This is not a major issue when using Nixpkgs overlays or
NixOS modules, since then the top-level flake composes those
overlays/modules into *its* version of Nixpkgs and all other versions
are ignored. Lock file computation has been made a bit more lazy so it
won't try to fetch all those versions of 'nixpkgs'.
However, in case it's necessary to minimize flake versions, there now
are two input attributes that allow this. First, you can copy an input
from another flake, as follows:
inputs.nixpkgs.follows = "dwarffs/nixpkgs";
This states that the calling flake's 'nixpkgs' input shall be the same
as the 'nixpkgs' input of the 'dwarffs' input.
Second, you can override inputs of inputs:
inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
inputs.nixops.inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
or equivalently, using 'follows':
inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
inputs.nixops.inputs.nixpkgs.follows = "nixpkgs";
This states that the 'nixpkgs' input of the 'nixops' input shall be
the same as the calling flake's 'nixpkgs' input.
Finally, at '-v' Nix now prints the changes to the lock file, e.g.
$ nix flake update ~/Misc/eelco-configurations/hagbard
inputs of flake 'git+file:///home/eelco/Misc/eelco-configurations?subdir=hagbard' changed:
updated 'nixpkgs': 'github:edolstra/nixpkgs/7845bf5f4b3013df1cf036e9c9c3a55a30331db9' -> 'github:edolstra/nixpkgs/03f3def66a104a221aac8b751eeb7075374848fd'
removed 'nixops'
removed 'nixops/nixops-aws'
removed 'nixops/nixops-hetzner'
removed 'nixops/nixpkgs'
2020-01-24 23:05:11 +02:00
|
|
|
inputs.emplace(inputAttr.name,
|
|
|
|
parseFlakeInput(state,
|
|
|
|
inputAttr.name,
|
|
|
|
inputAttr.value,
|
|
|
|
*inputAttr.pos));
|
|
|
|
}
|
|
|
|
|
|
|
|
return inputs;
|
|
|
|
}
|
|
|
|
|
2020-02-02 13:41:23 +02:00
|
|
|
static Flake getFlake(
|
|
|
|
EvalState & state,
|
|
|
|
const FlakeRef & originalRef,
|
|
|
|
bool allowLookup,
|
|
|
|
FlakeCache & flakeCache)
|
2018-11-30 17:11:15 +02:00
|
|
|
{
|
2020-04-06 15:56:13 +03:00
|
|
|
auto [sourceInfo, resolvedRef, lockedRef] = fetchOrSubstituteTree(
|
Remove TreeInfo
The attributes previously stored in TreeInfo (narHash, revCount,
lastModified) are now stored in Input. This makes it less arbitrary
what attributes are stored where.
As a result, the lock file format has changed. An entry like
"info": {
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github"
},
is now stored as
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github",
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
The 'Input' class is now a dumb set of attributes. All the fetcher
implementations subclass InputScheme, not Input. This simplifies the
API.
Also, fix substitution of flake inputs. This was broken since lazy
flake fetching started using fetchTree internally.
2020-05-30 01:44:11 +03:00
|
|
|
state, originalRef, allowLookup, flakeCache);
|
2019-02-12 21:35:03 +02:00
|
|
|
|
2019-05-01 21:38:41 +03:00
|
|
|
// Guard against symlink attacks.
|
2020-02-02 01:05:53 +02:00
|
|
|
auto flakeFile = canonPath(sourceInfo.actualPath + "/" + lockedRef.subdir + "/flake.nix");
|
2020-01-21 17:27:53 +02:00
|
|
|
if (!isInDir(flakeFile, sourceInfo.actualPath))
|
|
|
|
throw Error("'flake.nix' file of flake '%s' escapes from '%s'",
|
2020-02-02 01:05:53 +02:00
|
|
|
lockedRef, state.store->printStorePath(sourceInfo.storePath));
|
2020-01-21 17:27:53 +02:00
|
|
|
|
|
|
|
Flake flake {
|
|
|
|
.originalRef = originalRef,
|
2020-04-06 15:56:13 +03:00
|
|
|
.resolvedRef = resolvedRef,
|
2020-02-02 01:05:53 +02:00
|
|
|
.lockedRef = lockedRef,
|
2020-01-21 17:27:53 +02:00
|
|
|
.sourceInfo = std::make_shared<fetchers::Tree>(std::move(sourceInfo))
|
|
|
|
};
|
2019-05-01 12:38:48 +03:00
|
|
|
|
2020-01-21 17:27:53 +02:00
|
|
|
if (!pathExists(flakeFile))
|
2020-02-02 01:05:53 +02:00
|
|
|
throw Error("source tree referenced by '%s' does not contain a '%s/flake.nix' file", lockedRef, lockedRef.subdir);
|
2019-04-19 12:43:56 +03:00
|
|
|
|
2018-11-29 20:18:36 +02:00
|
|
|
Value vInfo;
|
2020-01-21 17:27:53 +02:00
|
|
|
state.evalFile(flakeFile, vInfo, true); // FIXME: symlink attack
|
2018-11-29 20:18:36 +02:00
|
|
|
|
2020-07-06 17:40:10 +03:00
|
|
|
expectType(state, tAttrs, vInfo, Pos(foFile, state.symbols.create(flakeFile), 0, 0));
|
2018-11-29 20:18:36 +02:00
|
|
|
|
2020-04-10 11:24:09 +03:00
|
|
|
auto sEdition = state.symbols.create("edition"); // FIXME: remove soon
|
2019-07-11 14:54:53 +03:00
|
|
|
|
2020-04-10 11:24:09 +03:00
|
|
|
if (vInfo.attrs->get(sEdition))
|
2020-04-20 16:28:56 +03:00
|
|
|
warn("flake '%s' has deprecated attribute 'edition'", lockedRef);
|
2020-04-10 11:24:09 +03:00
|
|
|
|
2019-09-09 17:34:44 +03:00
|
|
|
if (auto description = vInfo.attrs->get(state.sDescription)) {
|
2020-02-14 23:45:33 +02:00
|
|
|
expectType(state, tString, *description->value, *description->pos);
|
|
|
|
flake.description = description->value->string.s;
|
2019-09-09 17:34:44 +03:00
|
|
|
}
|
2018-11-29 20:18:36 +02:00
|
|
|
|
2019-05-30 00:09:23 +03:00
|
|
|
auto sInputs = state.symbols.create("inputs");
|
2019-05-29 16:12:22 +03:00
|
|
|
|
2020-02-14 23:45:33 +02:00
|
|
|
if (auto inputs = vInfo.attrs->get(sInputs))
|
|
|
|
flake.inputs = parseFlakeInputs(state, inputs->value, *inputs->pos);
|
2019-03-21 10:30:16 +02:00
|
|
|
|
2019-05-30 00:09:23 +03:00
|
|
|
auto sOutputs = state.symbols.create("outputs");
|
2019-05-29 16:12:22 +03:00
|
|
|
|
2019-05-30 00:09:23 +03:00
|
|
|
if (auto outputs = vInfo.attrs->get(sOutputs)) {
|
2020-02-14 23:45:33 +02:00
|
|
|
expectType(state, tLambda, *outputs->value, *outputs->pos);
|
2020-04-16 17:54:34 +03:00
|
|
|
flake.vOutputs = allocRootValue(outputs->value);
|
2019-08-30 12:22:34 +03:00
|
|
|
|
2020-04-16 17:54:34 +03:00
|
|
|
if ((*flake.vOutputs)->lambda.fun->matchAttrs) {
|
|
|
|
for (auto & formal : (*flake.vOutputs)->lambda.fun->formals->formals) {
|
2019-08-30 17:27:51 +03:00
|
|
|
if (formal.name != state.sSelf)
|
Respect lock files of inputs + fine-grained lock file control
When computing a lock file, we now respect the lock files of flake
inputs. This is important for usability / reproducibility. For
example, the 'nixops' flake depends on the 'nixops-aws' and
'nixops-hetzner' repositories. So when the 'nixops' flake is used in
another flake, we want the versions of 'nixops-aws' and
'nixops-hetzner' locked by the the 'nixops' flake because those
presumably have been tested.
This can lead to a proliferation of versions of flakes like 'nixpkgs'
(since every flake's lock file could depend on a different version of
'nixpkgs'). This is not a major issue when using Nixpkgs overlays or
NixOS modules, since then the top-level flake composes those
overlays/modules into *its* version of Nixpkgs and all other versions
are ignored. Lock file computation has been made a bit more lazy so it
won't try to fetch all those versions of 'nixpkgs'.
However, in case it's necessary to minimize flake versions, there now
are two input attributes that allow this. First, you can copy an input
from another flake, as follows:
inputs.nixpkgs.follows = "dwarffs/nixpkgs";
This states that the calling flake's 'nixpkgs' input shall be the same
as the 'nixpkgs' input of the 'dwarffs' input.
Second, you can override inputs of inputs:
inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
inputs.nixops.inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
or equivalently, using 'follows':
inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
inputs.nixops.inputs.nixpkgs.follows = "nixpkgs";
This states that the 'nixpkgs' input of the 'nixops' input shall be
the same as the calling flake's 'nixpkgs' input.
Finally, at '-v' Nix now prints the changes to the lock file, e.g.
$ nix flake update ~/Misc/eelco-configurations/hagbard
inputs of flake 'git+file:///home/eelco/Misc/eelco-configurations?subdir=hagbard' changed:
updated 'nixpkgs': 'github:edolstra/nixpkgs/7845bf5f4b3013df1cf036e9c9c3a55a30331db9' -> 'github:edolstra/nixpkgs/03f3def66a104a221aac8b751eeb7075374848fd'
removed 'nixops'
removed 'nixops/nixops-aws'
removed 'nixops/nixops-hetzner'
removed 'nixops/nixpkgs'
2020-01-24 23:05:11 +02:00
|
|
|
flake.inputs.emplace(formal.name, FlakeInput {
|
|
|
|
.ref = parseFlakeRef(formal.name)
|
|
|
|
});
|
2019-08-30 12:22:34 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-29 20:18:36 +02:00
|
|
|
} else
|
2020-02-02 13:41:23 +02:00
|
|
|
throw Error("flake '%s' lacks attribute 'outputs'", lockedRef);
|
2018-11-29 20:18:36 +02:00
|
|
|
|
2019-05-29 16:12:22 +03:00
|
|
|
for (auto & attr : *vInfo.attrs) {
|
2019-07-11 14:54:53 +03:00
|
|
|
if (attr.name != sEdition &&
|
2019-05-29 16:12:22 +03:00
|
|
|
attr.name != state.sDescription &&
|
2019-05-30 00:09:23 +03:00
|
|
|
attr.name != sInputs &&
|
|
|
|
attr.name != sOutputs)
|
2019-05-29 16:12:22 +03:00
|
|
|
throw Error("flake '%s' has an unsupported attribute '%s', at %s",
|
2020-02-02 13:41:23 +02:00
|
|
|
lockedRef, attr.name, *attr.pos);
|
2019-05-29 16:12:22 +03:00
|
|
|
}
|
|
|
|
|
2018-11-29 20:18:36 +02:00
|
|
|
return flake;
|
|
|
|
}
|
|
|
|
|
2019-09-19 00:59:45 +03:00
|
|
|
Flake getFlake(EvalState & state, const FlakeRef & originalRef, bool allowLookup)
|
|
|
|
{
|
2020-01-29 22:10:27 +02:00
|
|
|
FlakeCache flakeCache;
|
Remove TreeInfo
The attributes previously stored in TreeInfo (narHash, revCount,
lastModified) are now stored in Input. This makes it less arbitrary
what attributes are stored where.
As a result, the lock file format has changed. An entry like
"info": {
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github"
},
is now stored as
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github",
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
The 'Input' class is now a dumb set of attributes. All the fetcher
implementations subclass InputScheme, not Input. This simplifies the
API.
Also, fix substitution of flake inputs. This was broken since lazy
flake fetching started using fetchTree internally.
2020-05-30 01:44:11 +03:00
|
|
|
return getFlake(state, originalRef, allowLookup, flakeCache);
|
2019-03-21 10:30:16 +02:00
|
|
|
}
|
|
|
|
|
Respect lock files of inputs + fine-grained lock file control
When computing a lock file, we now respect the lock files of flake
inputs. This is important for usability / reproducibility. For
example, the 'nixops' flake depends on the 'nixops-aws' and
'nixops-hetzner' repositories. So when the 'nixops' flake is used in
another flake, we want the versions of 'nixops-aws' and
'nixops-hetzner' locked by the the 'nixops' flake because those
presumably have been tested.
This can lead to a proliferation of versions of flakes like 'nixpkgs'
(since every flake's lock file could depend on a different version of
'nixpkgs'). This is not a major issue when using Nixpkgs overlays or
NixOS modules, since then the top-level flake composes those
overlays/modules into *its* version of Nixpkgs and all other versions
are ignored. Lock file computation has been made a bit more lazy so it
won't try to fetch all those versions of 'nixpkgs'.
However, in case it's necessary to minimize flake versions, there now
are two input attributes that allow this. First, you can copy an input
from another flake, as follows:
inputs.nixpkgs.follows = "dwarffs/nixpkgs";
This states that the calling flake's 'nixpkgs' input shall be the same
as the 'nixpkgs' input of the 'dwarffs' input.
Second, you can override inputs of inputs:
inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
inputs.nixops.inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
or equivalently, using 'follows':
inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
inputs.nixops.inputs.nixpkgs.follows = "nixpkgs";
This states that the 'nixpkgs' input of the 'nixops' input shall be
the same as the calling flake's 'nixpkgs' input.
Finally, at '-v' Nix now prints the changes to the lock file, e.g.
$ nix flake update ~/Misc/eelco-configurations/hagbard
inputs of flake 'git+file:///home/eelco/Misc/eelco-configurations?subdir=hagbard' changed:
updated 'nixpkgs': 'github:edolstra/nixpkgs/7845bf5f4b3013df1cf036e9c9c3a55a30331db9' -> 'github:edolstra/nixpkgs/03f3def66a104a221aac8b751eeb7075374848fd'
removed 'nixops'
removed 'nixops/nixops-aws'
removed 'nixops/nixops-hetzner'
removed 'nixops/nixpkgs'
2020-01-24 23:05:11 +02:00
|
|
|
/* Compute an in-memory lock file for the specified top-level flake,
|
2019-06-04 22:07:55 +03:00
|
|
|
and optionally write it to file, it the flake is writable. */
|
2020-01-22 21:59:59 +02:00
|
|
|
LockedFlake lockFlake(
|
|
|
|
EvalState & state,
|
|
|
|
const FlakeRef & topRef,
|
2020-01-29 15:57:57 +02:00
|
|
|
const LockFlags & lockFlags)
|
2019-05-01 12:38:48 +03:00
|
|
|
{
|
2019-10-16 18:45:09 +03:00
|
|
|
settings.requireExperimentalFeature("flakes");
|
|
|
|
|
2020-01-29 22:10:27 +02:00
|
|
|
FlakeCache flakeCache;
|
Respect lock files of inputs + fine-grained lock file control
When computing a lock file, we now respect the lock files of flake
inputs. This is important for usability / reproducibility. For
example, the 'nixops' flake depends on the 'nixops-aws' and
'nixops-hetzner' repositories. So when the 'nixops' flake is used in
another flake, we want the versions of 'nixops-aws' and
'nixops-hetzner' locked by the the 'nixops' flake because those
presumably have been tested.
This can lead to a proliferation of versions of flakes like 'nixpkgs'
(since every flake's lock file could depend on a different version of
'nixpkgs'). This is not a major issue when using Nixpkgs overlays or
NixOS modules, since then the top-level flake composes those
overlays/modules into *its* version of Nixpkgs and all other versions
are ignored. Lock file computation has been made a bit more lazy so it
won't try to fetch all those versions of 'nixpkgs'.
However, in case it's necessary to minimize flake versions, there now
are two input attributes that allow this. First, you can copy an input
from another flake, as follows:
inputs.nixpkgs.follows = "dwarffs/nixpkgs";
This states that the calling flake's 'nixpkgs' input shall be the same
as the 'nixpkgs' input of the 'dwarffs' input.
Second, you can override inputs of inputs:
inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
inputs.nixops.inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
or equivalently, using 'follows':
inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
inputs.nixops.inputs.nixpkgs.follows = "nixpkgs";
This states that the 'nixpkgs' input of the 'nixops' input shall be
the same as the calling flake's 'nixpkgs' input.
Finally, at '-v' Nix now prints the changes to the lock file, e.g.
$ nix flake update ~/Misc/eelco-configurations/hagbard
inputs of flake 'git+file:///home/eelco/Misc/eelco-configurations?subdir=hagbard' changed:
updated 'nixpkgs': 'github:edolstra/nixpkgs/7845bf5f4b3013df1cf036e9c9c3a55a30331db9' -> 'github:edolstra/nixpkgs/03f3def66a104a221aac8b751eeb7075374848fd'
removed 'nixops'
removed 'nixops/nixops-aws'
removed 'nixops/nixops-hetzner'
removed 'nixops/nixpkgs'
2020-01-24 23:05:11 +02:00
|
|
|
|
Remove TreeInfo
The attributes previously stored in TreeInfo (narHash, revCount,
lastModified) are now stored in Input. This makes it less arbitrary
what attributes are stored where.
As a result, the lock file format has changed. An entry like
"info": {
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github"
},
is now stored as
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github",
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
The 'Input' class is now a dumb set of attributes. All the fetcher
implementations subclass InputScheme, not Input. This simplifies the
API.
Also, fix substitution of flake inputs. This was broken since lazy
flake fetching started using fetchTree internally.
2020-05-30 01:44:11 +03:00
|
|
|
auto flake = getFlake(state, topRef, lockFlags.useRegistries, flakeCache);
|
2019-06-04 20:10:35 +03:00
|
|
|
|
2020-03-27 22:08:41 +02:00
|
|
|
// FIXME: symlink attack
|
|
|
|
auto oldLockFile = LockFile::read(
|
|
|
|
flake.sourceInfo->actualPath + "/" + flake.lockedRef.subdir + "/flake.lock");
|
2019-05-01 12:38:48 +03:00
|
|
|
|
2019-10-21 15:57:01 +03:00
|
|
|
debug("old lock file: %s", oldLockFile);
|
|
|
|
|
Respect lock files of inputs + fine-grained lock file control
When computing a lock file, we now respect the lock files of flake
inputs. This is important for usability / reproducibility. For
example, the 'nixops' flake depends on the 'nixops-aws' and
'nixops-hetzner' repositories. So when the 'nixops' flake is used in
another flake, we want the versions of 'nixops-aws' and
'nixops-hetzner' locked by the the 'nixops' flake because those
presumably have been tested.
This can lead to a proliferation of versions of flakes like 'nixpkgs'
(since every flake's lock file could depend on a different version of
'nixpkgs'). This is not a major issue when using Nixpkgs overlays or
NixOS modules, since then the top-level flake composes those
overlays/modules into *its* version of Nixpkgs and all other versions
are ignored. Lock file computation has been made a bit more lazy so it
won't try to fetch all those versions of 'nixpkgs'.
However, in case it's necessary to minimize flake versions, there now
are two input attributes that allow this. First, you can copy an input
from another flake, as follows:
inputs.nixpkgs.follows = "dwarffs/nixpkgs";
This states that the calling flake's 'nixpkgs' input shall be the same
as the 'nixpkgs' input of the 'dwarffs' input.
Second, you can override inputs of inputs:
inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
inputs.nixops.inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
or equivalently, using 'follows':
inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
inputs.nixops.inputs.nixpkgs.follows = "nixpkgs";
This states that the 'nixpkgs' input of the 'nixops' input shall be
the same as the calling flake's 'nixpkgs' input.
Finally, at '-v' Nix now prints the changes to the lock file, e.g.
$ nix flake update ~/Misc/eelco-configurations/hagbard
inputs of flake 'git+file:///home/eelco/Misc/eelco-configurations?subdir=hagbard' changed:
updated 'nixpkgs': 'github:edolstra/nixpkgs/7845bf5f4b3013df1cf036e9c9c3a55a30331db9' -> 'github:edolstra/nixpkgs/03f3def66a104a221aac8b751eeb7075374848fd'
removed 'nixops'
removed 'nixops/nixops-aws'
removed 'nixops/nixops-hetzner'
removed 'nixops/nixpkgs'
2020-01-24 23:05:11 +02:00
|
|
|
// FIXME: check whether all overrides are used.
|
|
|
|
std::map<InputPath, FlakeInput> overrides;
|
2020-03-28 20:09:36 +02:00
|
|
|
std::set<InputPath> overridesUsed, updatesUsed;
|
Respect lock files of inputs + fine-grained lock file control
When computing a lock file, we now respect the lock files of flake
inputs. This is important for usability / reproducibility. For
example, the 'nixops' flake depends on the 'nixops-aws' and
'nixops-hetzner' repositories. So when the 'nixops' flake is used in
another flake, we want the versions of 'nixops-aws' and
'nixops-hetzner' locked by the the 'nixops' flake because those
presumably have been tested.
This can lead to a proliferation of versions of flakes like 'nixpkgs'
(since every flake's lock file could depend on a different version of
'nixpkgs'). This is not a major issue when using Nixpkgs overlays or
NixOS modules, since then the top-level flake composes those
overlays/modules into *its* version of Nixpkgs and all other versions
are ignored. Lock file computation has been made a bit more lazy so it
won't try to fetch all those versions of 'nixpkgs'.
However, in case it's necessary to minimize flake versions, there now
are two input attributes that allow this. First, you can copy an input
from another flake, as follows:
inputs.nixpkgs.follows = "dwarffs/nixpkgs";
This states that the calling flake's 'nixpkgs' input shall be the same
as the 'nixpkgs' input of the 'dwarffs' input.
Second, you can override inputs of inputs:
inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
inputs.nixops.inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
or equivalently, using 'follows':
inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
inputs.nixops.inputs.nixpkgs.follows = "nixpkgs";
This states that the 'nixpkgs' input of the 'nixops' input shall be
the same as the calling flake's 'nixpkgs' input.
Finally, at '-v' Nix now prints the changes to the lock file, e.g.
$ nix flake update ~/Misc/eelco-configurations/hagbard
inputs of flake 'git+file:///home/eelco/Misc/eelco-configurations?subdir=hagbard' changed:
updated 'nixpkgs': 'github:edolstra/nixpkgs/7845bf5f4b3013df1cf036e9c9c3a55a30331db9' -> 'github:edolstra/nixpkgs/03f3def66a104a221aac8b751eeb7075374848fd'
removed 'nixops'
removed 'nixops/nixops-aws'
removed 'nixops/nixops-hetzner'
removed 'nixops/nixpkgs'
2020-01-24 23:05:11 +02:00
|
|
|
|
2020-01-29 15:57:57 +02:00
|
|
|
for (auto & i : lockFlags.inputOverrides)
|
|
|
|
overrides.insert_or_assign(i.first, FlakeInput { .ref = i.second });
|
|
|
|
|
2020-03-27 22:08:41 +02:00
|
|
|
LockFile newLockFile;
|
|
|
|
|
|
|
|
std::vector<FlakeRef> parents;
|
|
|
|
|
|
|
|
std::function<void(
|
|
|
|
const FlakeInputs & flakeInputs,
|
|
|
|
std::shared_ptr<Node> node,
|
|
|
|
const InputPath & inputPathPrefix,
|
|
|
|
std::shared_ptr<const Node> oldNode)>
|
|
|
|
computeLocks;
|
|
|
|
|
|
|
|
computeLocks = [&](
|
|
|
|
const FlakeInputs & flakeInputs,
|
|
|
|
std::shared_ptr<Node> node,
|
|
|
|
const InputPath & inputPathPrefix,
|
|
|
|
std::shared_ptr<const Node> oldNode)
|
|
|
|
{
|
2020-06-10 16:20:00 +03:00
|
|
|
debug("computing lock file node '%s'", printInputPath(inputPathPrefix));
|
2020-03-27 22:08:41 +02:00
|
|
|
|
|
|
|
/* Get the overrides (i.e. attributes of the form
|
|
|
|
'inputs.nixops.inputs.nixpkgs.url = ...'). */
|
|
|
|
// FIXME: check this
|
|
|
|
for (auto & [id, input] : flake.inputs) {
|
|
|
|
for (auto & [idOverride, inputOverride] : input.overrides) {
|
Respect lock files of inputs + fine-grained lock file control
When computing a lock file, we now respect the lock files of flake
inputs. This is important for usability / reproducibility. For
example, the 'nixops' flake depends on the 'nixops-aws' and
'nixops-hetzner' repositories. So when the 'nixops' flake is used in
another flake, we want the versions of 'nixops-aws' and
'nixops-hetzner' locked by the the 'nixops' flake because those
presumably have been tested.
This can lead to a proliferation of versions of flakes like 'nixpkgs'
(since every flake's lock file could depend on a different version of
'nixpkgs'). This is not a major issue when using Nixpkgs overlays or
NixOS modules, since then the top-level flake composes those
overlays/modules into *its* version of Nixpkgs and all other versions
are ignored. Lock file computation has been made a bit more lazy so it
won't try to fetch all those versions of 'nixpkgs'.
However, in case it's necessary to minimize flake versions, there now
are two input attributes that allow this. First, you can copy an input
from another flake, as follows:
inputs.nixpkgs.follows = "dwarffs/nixpkgs";
This states that the calling flake's 'nixpkgs' input shall be the same
as the 'nixpkgs' input of the 'dwarffs' input.
Second, you can override inputs of inputs:
inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
inputs.nixops.inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
or equivalently, using 'follows':
inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
inputs.nixops.inputs.nixpkgs.follows = "nixpkgs";
This states that the 'nixpkgs' input of the 'nixops' input shall be
the same as the calling flake's 'nixpkgs' input.
Finally, at '-v' Nix now prints the changes to the lock file, e.g.
$ nix flake update ~/Misc/eelco-configurations/hagbard
inputs of flake 'git+file:///home/eelco/Misc/eelco-configurations?subdir=hagbard' changed:
updated 'nixpkgs': 'github:edolstra/nixpkgs/7845bf5f4b3013df1cf036e9c9c3a55a30331db9' -> 'github:edolstra/nixpkgs/03f3def66a104a221aac8b751eeb7075374848fd'
removed 'nixops'
removed 'nixops/nixops-aws'
removed 'nixops/nixops-hetzner'
removed 'nixops/nixpkgs'
2020-01-24 23:05:11 +02:00
|
|
|
auto inputPath(inputPathPrefix);
|
|
|
|
inputPath.push_back(id);
|
2020-03-27 22:08:41 +02:00
|
|
|
inputPath.push_back(idOverride);
|
|
|
|
overrides.insert_or_assign(inputPath, inputOverride);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Go over the flake inputs, resolve/fetch them if
|
|
|
|
necessary (i.e. if they're new or the flakeref changed
|
|
|
|
from what's in the lock file). */
|
|
|
|
for (auto & [id, input2] : flakeInputs) {
|
|
|
|
auto inputPath(inputPathPrefix);
|
|
|
|
inputPath.push_back(id);
|
2020-06-10 16:20:00 +03:00
|
|
|
auto inputPathS = printInputPath(inputPath);
|
|
|
|
debug("computing input '%s'", inputPathS);
|
2020-03-27 22:08:41 +02:00
|
|
|
|
|
|
|
/* Do we have an override for this input from one of the
|
|
|
|
ancestors? */
|
|
|
|
auto i = overrides.find(inputPath);
|
|
|
|
bool hasOverride = i != overrides.end();
|
2020-03-28 20:09:36 +02:00
|
|
|
if (hasOverride) overridesUsed.insert(inputPath);
|
2020-03-27 22:08:41 +02:00
|
|
|
auto & input = hasOverride ? i->second : input2;
|
|
|
|
|
|
|
|
/* Resolve 'follows' later (since it may refer to an input
|
|
|
|
path we haven't processed yet. */
|
|
|
|
if (input.follows) {
|
2020-06-11 15:40:21 +03:00
|
|
|
InputPath target;
|
|
|
|
if (hasOverride || input.absolute)
|
2020-03-27 22:08:41 +02:00
|
|
|
/* 'follows' from an override is relative to the
|
|
|
|
root of the graph. */
|
2020-06-11 15:40:21 +03:00
|
|
|
target = *input.follows;
|
2020-03-27 22:08:41 +02:00
|
|
|
else {
|
|
|
|
/* Otherwise, it's relative to the current flake. */
|
2020-06-11 15:40:21 +03:00
|
|
|
target = inputPathPrefix;
|
|
|
|
for (auto & i : *input.follows) target.push_back(i);
|
Respect lock files of inputs + fine-grained lock file control
When computing a lock file, we now respect the lock files of flake
inputs. This is important for usability / reproducibility. For
example, the 'nixops' flake depends on the 'nixops-aws' and
'nixops-hetzner' repositories. So when the 'nixops' flake is used in
another flake, we want the versions of 'nixops-aws' and
'nixops-hetzner' locked by the the 'nixops' flake because those
presumably have been tested.
This can lead to a proliferation of versions of flakes like 'nixpkgs'
(since every flake's lock file could depend on a different version of
'nixpkgs'). This is not a major issue when using Nixpkgs overlays or
NixOS modules, since then the top-level flake composes those
overlays/modules into *its* version of Nixpkgs and all other versions
are ignored. Lock file computation has been made a bit more lazy so it
won't try to fetch all those versions of 'nixpkgs'.
However, in case it's necessary to minimize flake versions, there now
are two input attributes that allow this. First, you can copy an input
from another flake, as follows:
inputs.nixpkgs.follows = "dwarffs/nixpkgs";
This states that the calling flake's 'nixpkgs' input shall be the same
as the 'nixpkgs' input of the 'dwarffs' input.
Second, you can override inputs of inputs:
inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
inputs.nixops.inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
or equivalently, using 'follows':
inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
inputs.nixops.inputs.nixpkgs.follows = "nixpkgs";
This states that the 'nixpkgs' input of the 'nixops' input shall be
the same as the calling flake's 'nixpkgs' input.
Finally, at '-v' Nix now prints the changes to the lock file, e.g.
$ nix flake update ~/Misc/eelco-configurations/hagbard
inputs of flake 'git+file:///home/eelco/Misc/eelco-configurations?subdir=hagbard' changed:
updated 'nixpkgs': 'github:edolstra/nixpkgs/7845bf5f4b3013df1cf036e9c9c3a55a30331db9' -> 'github:edolstra/nixpkgs/03f3def66a104a221aac8b751eeb7075374848fd'
removed 'nixops'
removed 'nixops/nixops-aws'
removed 'nixops/nixops-hetzner'
removed 'nixops/nixpkgs'
2020-01-24 23:05:11 +02:00
|
|
|
}
|
2020-06-11 15:40:21 +03:00
|
|
|
debug("input '%s' follows '%s'", inputPathS, printInputPath(target));
|
|
|
|
node->inputs.insert_or_assign(id, target);
|
2020-03-27 22:08:41 +02:00
|
|
|
continue;
|
|
|
|
}
|
Respect lock files of inputs + fine-grained lock file control
When computing a lock file, we now respect the lock files of flake
inputs. This is important for usability / reproducibility. For
example, the 'nixops' flake depends on the 'nixops-aws' and
'nixops-hetzner' repositories. So when the 'nixops' flake is used in
another flake, we want the versions of 'nixops-aws' and
'nixops-hetzner' locked by the the 'nixops' flake because those
presumably have been tested.
This can lead to a proliferation of versions of flakes like 'nixpkgs'
(since every flake's lock file could depend on a different version of
'nixpkgs'). This is not a major issue when using Nixpkgs overlays or
NixOS modules, since then the top-level flake composes those
overlays/modules into *its* version of Nixpkgs and all other versions
are ignored. Lock file computation has been made a bit more lazy so it
won't try to fetch all those versions of 'nixpkgs'.
However, in case it's necessary to minimize flake versions, there now
are two input attributes that allow this. First, you can copy an input
from another flake, as follows:
inputs.nixpkgs.follows = "dwarffs/nixpkgs";
This states that the calling flake's 'nixpkgs' input shall be the same
as the 'nixpkgs' input of the 'dwarffs' input.
Second, you can override inputs of inputs:
inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
inputs.nixops.inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
or equivalently, using 'follows':
inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
inputs.nixops.inputs.nixpkgs.follows = "nixpkgs";
This states that the 'nixpkgs' input of the 'nixops' input shall be
the same as the calling flake's 'nixpkgs' input.
Finally, at '-v' Nix now prints the changes to the lock file, e.g.
$ nix flake update ~/Misc/eelco-configurations/hagbard
inputs of flake 'git+file:///home/eelco/Misc/eelco-configurations?subdir=hagbard' changed:
updated 'nixpkgs': 'github:edolstra/nixpkgs/7845bf5f4b3013df1cf036e9c9c3a55a30331db9' -> 'github:edolstra/nixpkgs/03f3def66a104a221aac8b751eeb7075374848fd'
removed 'nixops'
removed 'nixops/nixops-aws'
removed 'nixops/nixops-hetzner'
removed 'nixops/nixpkgs'
2020-01-24 23:05:11 +02:00
|
|
|
|
2020-06-11 15:40:21 +03:00
|
|
|
assert(input.ref);
|
|
|
|
|
2020-03-27 22:08:41 +02:00
|
|
|
/* Do we have an entry in the existing lock file? And we
|
|
|
|
don't have a --update-input flag for this input? */
|
2020-06-11 15:40:21 +03:00
|
|
|
std::shared_ptr<LockedNode> oldLock;
|
2020-03-12 23:06:57 +02:00
|
|
|
|
2020-03-28 20:09:36 +02:00
|
|
|
updatesUsed.insert(inputPath);
|
|
|
|
|
2020-06-11 15:40:21 +03:00
|
|
|
if (oldNode && !lockFlags.inputUpdates.count(inputPath))
|
|
|
|
if (auto oldLock2 = get(oldNode->inputs, id))
|
|
|
|
if (auto oldLock3 = std::get_if<0>(&*oldLock2))
|
|
|
|
oldLock = *oldLock3;
|
Respect lock files of inputs + fine-grained lock file control
When computing a lock file, we now respect the lock files of flake
inputs. This is important for usability / reproducibility. For
example, the 'nixops' flake depends on the 'nixops-aws' and
'nixops-hetzner' repositories. So when the 'nixops' flake is used in
another flake, we want the versions of 'nixops-aws' and
'nixops-hetzner' locked by the the 'nixops' flake because those
presumably have been tested.
This can lead to a proliferation of versions of flakes like 'nixpkgs'
(since every flake's lock file could depend on a different version of
'nixpkgs'). This is not a major issue when using Nixpkgs overlays or
NixOS modules, since then the top-level flake composes those
overlays/modules into *its* version of Nixpkgs and all other versions
are ignored. Lock file computation has been made a bit more lazy so it
won't try to fetch all those versions of 'nixpkgs'.
However, in case it's necessary to minimize flake versions, there now
are two input attributes that allow this. First, you can copy an input
from another flake, as follows:
inputs.nixpkgs.follows = "dwarffs/nixpkgs";
This states that the calling flake's 'nixpkgs' input shall be the same
as the 'nixpkgs' input of the 'dwarffs' input.
Second, you can override inputs of inputs:
inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
inputs.nixops.inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
or equivalently, using 'follows':
inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
inputs.nixops.inputs.nixpkgs.follows = "nixpkgs";
This states that the 'nixpkgs' input of the 'nixops' input shall be
the same as the calling flake's 'nixpkgs' input.
Finally, at '-v' Nix now prints the changes to the lock file, e.g.
$ nix flake update ~/Misc/eelco-configurations/hagbard
inputs of flake 'git+file:///home/eelco/Misc/eelco-configurations?subdir=hagbard' changed:
updated 'nixpkgs': 'github:edolstra/nixpkgs/7845bf5f4b3013df1cf036e9c9c3a55a30331db9' -> 'github:edolstra/nixpkgs/03f3def66a104a221aac8b751eeb7075374848fd'
removed 'nixops'
removed 'nixops/nixops-aws'
removed 'nixops/nixops-hetzner'
removed 'nixops/nixpkgs'
2020-01-24 23:05:11 +02:00
|
|
|
|
2020-03-27 22:08:41 +02:00
|
|
|
if (oldLock
|
2020-06-11 15:40:21 +03:00
|
|
|
&& oldLock->originalRef == *input.ref
|
2020-03-27 22:08:41 +02:00
|
|
|
&& !hasOverride)
|
|
|
|
{
|
|
|
|
debug("keeping existing input '%s'", inputPathS);
|
|
|
|
|
|
|
|
/* Copy the input from the old lock since its flakeref
|
|
|
|
didn't change and there is no override from a
|
|
|
|
higher level flake. */
|
|
|
|
auto childNode = std::make_shared<LockedNode>(
|
Remove TreeInfo
The attributes previously stored in TreeInfo (narHash, revCount,
lastModified) are now stored in Input. This makes it less arbitrary
what attributes are stored where.
As a result, the lock file format has changed. An entry like
"info": {
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github"
},
is now stored as
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github",
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
The 'Input' class is now a dumb set of attributes. All the fetcher
implementations subclass InputScheme, not Input. This simplifies the
API.
Also, fix substitution of flake inputs. This was broken since lazy
flake fetching started using fetchTree internally.
2020-05-30 01:44:11 +03:00
|
|
|
oldLock->lockedRef, oldLock->originalRef, oldLock->isFlake);
|
2020-03-27 22:08:41 +02:00
|
|
|
|
|
|
|
node->inputs.insert_or_assign(id, childNode);
|
|
|
|
|
|
|
|
/* If we have an --update-input flag for an input
|
|
|
|
of this input, then we must fetch the flake to
|
2020-09-22 21:07:06 +03:00
|
|
|
update it. */
|
2020-03-27 22:08:41 +02:00
|
|
|
auto lb = lockFlags.inputUpdates.lower_bound(inputPath);
|
|
|
|
|
|
|
|
auto hasChildUpdate =
|
|
|
|
lb != lockFlags.inputUpdates.end()
|
|
|
|
&& lb->size() > inputPath.size()
|
|
|
|
&& std::equal(inputPath.begin(), inputPath.end(), lb->begin());
|
|
|
|
|
|
|
|
if (hasChildUpdate) {
|
|
|
|
auto inputFlake = getFlake(
|
Remove TreeInfo
The attributes previously stored in TreeInfo (narHash, revCount,
lastModified) are now stored in Input. This makes it less arbitrary
what attributes are stored where.
As a result, the lock file format has changed. An entry like
"info": {
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github"
},
is now stored as
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github",
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
The 'Input' class is now a dumb set of attributes. All the fetcher
implementations subclass InputScheme, not Input. This simplifies the
API.
Also, fix substitution of flake inputs. This was broken since lazy
flake fetching started using fetchTree internally.
2020-05-30 01:44:11 +03:00
|
|
|
state, oldLock->lockedRef, false, flakeCache);
|
2020-03-27 22:08:41 +02:00
|
|
|
computeLocks(inputFlake.inputs, childNode, inputPath, oldLock);
|
|
|
|
} else {
|
|
|
|
/* No need to fetch this flake, we can be
|
|
|
|
lazy. However there may be new overrides on the
|
|
|
|
inputs of this flake, so we need to check
|
|
|
|
those. */
|
|
|
|
FlakeInputs fakeInputs;
|
|
|
|
|
|
|
|
for (auto & i : oldLock->inputs) {
|
2020-06-11 15:40:21 +03:00
|
|
|
if (auto lockedNode = std::get_if<0>(&i.second)) {
|
2020-03-12 23:06:57 +02:00
|
|
|
fakeInputs.emplace(i.first, FlakeInput {
|
2020-06-11 15:40:21 +03:00
|
|
|
.ref = (*lockedNode)->originalRef,
|
|
|
|
.isFlake = (*lockedNode)->isFlake,
|
|
|
|
});
|
|
|
|
} else if (auto follows = std::get_if<1>(&i.second)) {
|
|
|
|
fakeInputs.emplace(i.first, FlakeInput {
|
|
|
|
.follows = *follows,
|
|
|
|
.absolute = true
|
2020-03-12 23:06:57 +02:00
|
|
|
});
|
2020-03-27 22:08:41 +02:00
|
|
|
}
|
Respect lock files of inputs + fine-grained lock file control
When computing a lock file, we now respect the lock files of flake
inputs. This is important for usability / reproducibility. For
example, the 'nixops' flake depends on the 'nixops-aws' and
'nixops-hetzner' repositories. So when the 'nixops' flake is used in
another flake, we want the versions of 'nixops-aws' and
'nixops-hetzner' locked by the the 'nixops' flake because those
presumably have been tested.
This can lead to a proliferation of versions of flakes like 'nixpkgs'
(since every flake's lock file could depend on a different version of
'nixpkgs'). This is not a major issue when using Nixpkgs overlays or
NixOS modules, since then the top-level flake composes those
overlays/modules into *its* version of Nixpkgs and all other versions
are ignored. Lock file computation has been made a bit more lazy so it
won't try to fetch all those versions of 'nixpkgs'.
However, in case it's necessary to minimize flake versions, there now
are two input attributes that allow this. First, you can copy an input
from another flake, as follows:
inputs.nixpkgs.follows = "dwarffs/nixpkgs";
This states that the calling flake's 'nixpkgs' input shall be the same
as the 'nixpkgs' input of the 'dwarffs' input.
Second, you can override inputs of inputs:
inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
inputs.nixops.inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
or equivalently, using 'follows':
inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
inputs.nixops.inputs.nixpkgs.follows = "nixpkgs";
This states that the 'nixpkgs' input of the 'nixops' input shall be
the same as the calling flake's 'nixpkgs' input.
Finally, at '-v' Nix now prints the changes to the lock file, e.g.
$ nix flake update ~/Misc/eelco-configurations/hagbard
inputs of flake 'git+file:///home/eelco/Misc/eelco-configurations?subdir=hagbard' changed:
updated 'nixpkgs': 'github:edolstra/nixpkgs/7845bf5f4b3013df1cf036e9c9c3a55a30331db9' -> 'github:edolstra/nixpkgs/03f3def66a104a221aac8b751eeb7075374848fd'
removed 'nixops'
removed 'nixops/nixops-aws'
removed 'nixops/nixops-hetzner'
removed 'nixops/nixpkgs'
2020-01-24 23:05:11 +02:00
|
|
|
}
|
|
|
|
|
2020-03-27 22:08:41 +02:00
|
|
|
computeLocks(fakeInputs, childNode, inputPath, oldLock);
|
|
|
|
}
|
Respect lock files of inputs + fine-grained lock file control
When computing a lock file, we now respect the lock files of flake
inputs. This is important for usability / reproducibility. For
example, the 'nixops' flake depends on the 'nixops-aws' and
'nixops-hetzner' repositories. So when the 'nixops' flake is used in
another flake, we want the versions of 'nixops-aws' and
'nixops-hetzner' locked by the the 'nixops' flake because those
presumably have been tested.
This can lead to a proliferation of versions of flakes like 'nixpkgs'
(since every flake's lock file could depend on a different version of
'nixpkgs'). This is not a major issue when using Nixpkgs overlays or
NixOS modules, since then the top-level flake composes those
overlays/modules into *its* version of Nixpkgs and all other versions
are ignored. Lock file computation has been made a bit more lazy so it
won't try to fetch all those versions of 'nixpkgs'.
However, in case it's necessary to minimize flake versions, there now
are two input attributes that allow this. First, you can copy an input
from another flake, as follows:
inputs.nixpkgs.follows = "dwarffs/nixpkgs";
This states that the calling flake's 'nixpkgs' input shall be the same
as the 'nixpkgs' input of the 'dwarffs' input.
Second, you can override inputs of inputs:
inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
inputs.nixops.inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
or equivalently, using 'follows':
inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
inputs.nixops.inputs.nixpkgs.follows = "nixpkgs";
This states that the 'nixpkgs' input of the 'nixops' input shall be
the same as the calling flake's 'nixpkgs' input.
Finally, at '-v' Nix now prints the changes to the lock file, e.g.
$ nix flake update ~/Misc/eelco-configurations/hagbard
inputs of flake 'git+file:///home/eelco/Misc/eelco-configurations?subdir=hagbard' changed:
updated 'nixpkgs': 'github:edolstra/nixpkgs/7845bf5f4b3013df1cf036e9c9c3a55a30331db9' -> 'github:edolstra/nixpkgs/03f3def66a104a221aac8b751eeb7075374848fd'
removed 'nixops'
removed 'nixops/nixops-aws'
removed 'nixops/nixops-hetzner'
removed 'nixops/nixpkgs'
2020-01-24 23:05:11 +02:00
|
|
|
|
2020-03-27 22:08:41 +02:00
|
|
|
} else {
|
|
|
|
/* We need to create a new lock file entry. So fetch
|
|
|
|
this input. */
|
2020-06-10 16:20:00 +03:00
|
|
|
debug("creating new input '%s'", inputPathS);
|
2020-03-27 22:08:41 +02:00
|
|
|
|
2020-06-11 15:40:21 +03:00
|
|
|
if (!lockFlags.allowMutable && !input.ref->input.isImmutable())
|
2020-03-27 22:08:41 +02:00
|
|
|
throw Error("cannot update flake input '%s' in pure mode", inputPathS);
|
|
|
|
|
|
|
|
if (input.isFlake) {
|
2020-06-11 15:40:21 +03:00
|
|
|
auto inputFlake = getFlake(state, *input.ref, lockFlags.useRegistries, flakeCache);
|
2020-03-27 22:08:41 +02:00
|
|
|
|
2020-04-03 15:06:29 +03:00
|
|
|
/* Note: in case of an --override-input, we use
|
|
|
|
the *original* ref (input2.ref) for the
|
|
|
|
"original" field, rather than the
|
|
|
|
override. This ensures that the override isn't
|
|
|
|
nuked the next time we update the lock
|
|
|
|
file. That is, overrides are sticky unless you
|
|
|
|
use --no-write-lock-file. */
|
2020-03-27 22:08:41 +02:00
|
|
|
auto childNode = std::make_shared<LockedNode>(
|
2020-06-11 15:40:21 +03:00
|
|
|
inputFlake.lockedRef, input2.ref ? *input2.ref : *input.ref);
|
2020-03-27 22:08:41 +02:00
|
|
|
|
|
|
|
node->inputs.insert_or_assign(id, childNode);
|
|
|
|
|
|
|
|
/* Guard against circular flake imports. */
|
|
|
|
for (auto & parent : parents)
|
2020-06-11 15:40:21 +03:00
|
|
|
if (parent == *input.ref)
|
2020-03-27 22:08:41 +02:00
|
|
|
throw Error("found circular import of flake '%s'", parent);
|
2020-06-11 15:40:21 +03:00
|
|
|
parents.push_back(*input.ref);
|
2020-03-27 22:08:41 +02:00
|
|
|
Finally cleanup([&]() { parents.pop_back(); });
|
|
|
|
|
|
|
|
/* Recursively process the inputs of this
|
|
|
|
flake. Also, unless we already have this flake
|
|
|
|
in the top-level lock file, use this flake's
|
|
|
|
own lock file. */
|
|
|
|
computeLocks(
|
|
|
|
inputFlake.inputs, childNode, inputPath,
|
|
|
|
oldLock
|
|
|
|
? std::dynamic_pointer_cast<const Node>(oldLock)
|
|
|
|
: LockFile::read(
|
|
|
|
inputFlake.sourceInfo->actualPath + "/" + inputFlake.lockedRef.subdir + "/flake.lock").root);
|
|
|
|
}
|
|
|
|
|
|
|
|
else {
|
2020-04-06 15:56:13 +03:00
|
|
|
auto [sourceInfo, resolvedRef, lockedRef] = fetchOrSubstituteTree(
|
2020-06-11 15:40:21 +03:00
|
|
|
state, *input.ref, lockFlags.useRegistries, flakeCache);
|
2020-03-27 22:08:41 +02:00
|
|
|
node->inputs.insert_or_assign(id,
|
2020-06-11 15:40:21 +03:00
|
|
|
std::make_shared<LockedNode>(lockedRef, *input.ref, false));
|
Respect lock files of inputs + fine-grained lock file control
When computing a lock file, we now respect the lock files of flake
inputs. This is important for usability / reproducibility. For
example, the 'nixops' flake depends on the 'nixops-aws' and
'nixops-hetzner' repositories. So when the 'nixops' flake is used in
another flake, we want the versions of 'nixops-aws' and
'nixops-hetzner' locked by the the 'nixops' flake because those
presumably have been tested.
This can lead to a proliferation of versions of flakes like 'nixpkgs'
(since every flake's lock file could depend on a different version of
'nixpkgs'). This is not a major issue when using Nixpkgs overlays or
NixOS modules, since then the top-level flake composes those
overlays/modules into *its* version of Nixpkgs and all other versions
are ignored. Lock file computation has been made a bit more lazy so it
won't try to fetch all those versions of 'nixpkgs'.
However, in case it's necessary to minimize flake versions, there now
are two input attributes that allow this. First, you can copy an input
from another flake, as follows:
inputs.nixpkgs.follows = "dwarffs/nixpkgs";
This states that the calling flake's 'nixpkgs' input shall be the same
as the 'nixpkgs' input of the 'dwarffs' input.
Second, you can override inputs of inputs:
inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
inputs.nixops.inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
or equivalently, using 'follows':
inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
inputs.nixops.inputs.nixpkgs.follows = "nixpkgs";
This states that the 'nixpkgs' input of the 'nixops' input shall be
the same as the calling flake's 'nixpkgs' input.
Finally, at '-v' Nix now prints the changes to the lock file, e.g.
$ nix flake update ~/Misc/eelco-configurations/hagbard
inputs of flake 'git+file:///home/eelco/Misc/eelco-configurations?subdir=hagbard' changed:
updated 'nixpkgs': 'github:edolstra/nixpkgs/7845bf5f4b3013df1cf036e9c9c3a55a30331db9' -> 'github:edolstra/nixpkgs/03f3def66a104a221aac8b751eeb7075374848fd'
removed 'nixops'
removed 'nixops/nixops-aws'
removed 'nixops/nixops-hetzner'
removed 'nixops/nixpkgs'
2020-01-24 23:05:11 +02:00
|
|
|
}
|
|
|
|
}
|
2020-03-27 22:08:41 +02:00
|
|
|
}
|
|
|
|
};
|
Respect lock files of inputs + fine-grained lock file control
When computing a lock file, we now respect the lock files of flake
inputs. This is important for usability / reproducibility. For
example, the 'nixops' flake depends on the 'nixops-aws' and
'nixops-hetzner' repositories. So when the 'nixops' flake is used in
another flake, we want the versions of 'nixops-aws' and
'nixops-hetzner' locked by the the 'nixops' flake because those
presumably have been tested.
This can lead to a proliferation of versions of flakes like 'nixpkgs'
(since every flake's lock file could depend on a different version of
'nixpkgs'). This is not a major issue when using Nixpkgs overlays or
NixOS modules, since then the top-level flake composes those
overlays/modules into *its* version of Nixpkgs and all other versions
are ignored. Lock file computation has been made a bit more lazy so it
won't try to fetch all those versions of 'nixpkgs'.
However, in case it's necessary to minimize flake versions, there now
are two input attributes that allow this. First, you can copy an input
from another flake, as follows:
inputs.nixpkgs.follows = "dwarffs/nixpkgs";
This states that the calling flake's 'nixpkgs' input shall be the same
as the 'nixpkgs' input of the 'dwarffs' input.
Second, you can override inputs of inputs:
inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
inputs.nixops.inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
or equivalently, using 'follows':
inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
inputs.nixops.inputs.nixpkgs.follows = "nixpkgs";
This states that the 'nixpkgs' input of the 'nixops' input shall be
the same as the calling flake's 'nixpkgs' input.
Finally, at '-v' Nix now prints the changes to the lock file, e.g.
$ nix flake update ~/Misc/eelco-configurations/hagbard
inputs of flake 'git+file:///home/eelco/Misc/eelco-configurations?subdir=hagbard' changed:
updated 'nixpkgs': 'github:edolstra/nixpkgs/7845bf5f4b3013df1cf036e9c9c3a55a30331db9' -> 'github:edolstra/nixpkgs/03f3def66a104a221aac8b751eeb7075374848fd'
removed 'nixops'
removed 'nixops/nixops-aws'
removed 'nixops/nixops-hetzner'
removed 'nixops/nixpkgs'
2020-01-24 23:05:11 +02:00
|
|
|
|
2020-03-27 22:08:41 +02:00
|
|
|
computeLocks(
|
|
|
|
flake.inputs, newLockFile.root, {},
|
|
|
|
lockFlags.recreateLockFile ? nullptr : oldLockFile.root);
|
Respect lock files of inputs + fine-grained lock file control
When computing a lock file, we now respect the lock files of flake
inputs. This is important for usability / reproducibility. For
example, the 'nixops' flake depends on the 'nixops-aws' and
'nixops-hetzner' repositories. So when the 'nixops' flake is used in
another flake, we want the versions of 'nixops-aws' and
'nixops-hetzner' locked by the the 'nixops' flake because those
presumably have been tested.
This can lead to a proliferation of versions of flakes like 'nixpkgs'
(since every flake's lock file could depend on a different version of
'nixpkgs'). This is not a major issue when using Nixpkgs overlays or
NixOS modules, since then the top-level flake composes those
overlays/modules into *its* version of Nixpkgs and all other versions
are ignored. Lock file computation has been made a bit more lazy so it
won't try to fetch all those versions of 'nixpkgs'.
However, in case it's necessary to minimize flake versions, there now
are two input attributes that allow this. First, you can copy an input
from another flake, as follows:
inputs.nixpkgs.follows = "dwarffs/nixpkgs";
This states that the calling flake's 'nixpkgs' input shall be the same
as the 'nixpkgs' input of the 'dwarffs' input.
Second, you can override inputs of inputs:
inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
inputs.nixops.inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
or equivalently, using 'follows':
inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
inputs.nixops.inputs.nixpkgs.follows = "nixpkgs";
This states that the 'nixpkgs' input of the 'nixops' input shall be
the same as the calling flake's 'nixpkgs' input.
Finally, at '-v' Nix now prints the changes to the lock file, e.g.
$ nix flake update ~/Misc/eelco-configurations/hagbard
inputs of flake 'git+file:///home/eelco/Misc/eelco-configurations?subdir=hagbard' changed:
updated 'nixpkgs': 'github:edolstra/nixpkgs/7845bf5f4b3013df1cf036e9c9c3a55a30331db9' -> 'github:edolstra/nixpkgs/03f3def66a104a221aac8b751eeb7075374848fd'
removed 'nixops'
removed 'nixops/nixops-aws'
removed 'nixops/nixops-hetzner'
removed 'nixops/nixpkgs'
2020-01-24 23:05:11 +02:00
|
|
|
|
2020-03-28 20:09:36 +02:00
|
|
|
for (auto & i : lockFlags.inputOverrides)
|
|
|
|
if (!overridesUsed.count(i.first))
|
|
|
|
warn("the flag '--override-input %s %s' does not match any input",
|
2020-06-10 16:20:00 +03:00
|
|
|
printInputPath(i.first), i.second);
|
2020-03-28 20:09:36 +02:00
|
|
|
|
|
|
|
for (auto & i : lockFlags.inputUpdates)
|
|
|
|
if (!updatesUsed.count(i))
|
2020-06-10 16:20:00 +03:00
|
|
|
warn("the flag '--update-input %s' does not match any input", printInputPath(i));
|
2020-03-28 20:09:36 +02:00
|
|
|
|
2020-06-12 00:34:02 +03:00
|
|
|
/* Check 'follows' inputs. */
|
|
|
|
newLockFile.check();
|
|
|
|
|
2020-01-24 14:07:03 +02:00
|
|
|
debug("new lock file: %s", newLockFile);
|
2019-10-21 15:57:01 +03:00
|
|
|
|
Respect lock files of inputs + fine-grained lock file control
When computing a lock file, we now respect the lock files of flake
inputs. This is important for usability / reproducibility. For
example, the 'nixops' flake depends on the 'nixops-aws' and
'nixops-hetzner' repositories. So when the 'nixops' flake is used in
another flake, we want the versions of 'nixops-aws' and
'nixops-hetzner' locked by the the 'nixops' flake because those
presumably have been tested.
This can lead to a proliferation of versions of flakes like 'nixpkgs'
(since every flake's lock file could depend on a different version of
'nixpkgs'). This is not a major issue when using Nixpkgs overlays or
NixOS modules, since then the top-level flake composes those
overlays/modules into *its* version of Nixpkgs and all other versions
are ignored. Lock file computation has been made a bit more lazy so it
won't try to fetch all those versions of 'nixpkgs'.
However, in case it's necessary to minimize flake versions, there now
are two input attributes that allow this. First, you can copy an input
from another flake, as follows:
inputs.nixpkgs.follows = "dwarffs/nixpkgs";
This states that the calling flake's 'nixpkgs' input shall be the same
as the 'nixpkgs' input of the 'dwarffs' input.
Second, you can override inputs of inputs:
inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
inputs.nixops.inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
or equivalently, using 'follows':
inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
inputs.nixops.inputs.nixpkgs.follows = "nixpkgs";
This states that the 'nixpkgs' input of the 'nixops' input shall be
the same as the calling flake's 'nixpkgs' input.
Finally, at '-v' Nix now prints the changes to the lock file, e.g.
$ nix flake update ~/Misc/eelco-configurations/hagbard
inputs of flake 'git+file:///home/eelco/Misc/eelco-configurations?subdir=hagbard' changed:
updated 'nixpkgs': 'github:edolstra/nixpkgs/7845bf5f4b3013df1cf036e9c9c3a55a30331db9' -> 'github:edolstra/nixpkgs/03f3def66a104a221aac8b751eeb7075374848fd'
removed 'nixops'
removed 'nixops/nixops-aws'
removed 'nixops/nixops-hetzner'
removed 'nixops/nixpkgs'
2020-01-24 23:05:11 +02:00
|
|
|
/* Check whether we need to / can write the new lock file. */
|
2020-01-24 14:07:03 +02:00
|
|
|
if (!(newLockFile == oldLockFile)) {
|
Respect lock files of inputs + fine-grained lock file control
When computing a lock file, we now respect the lock files of flake
inputs. This is important for usability / reproducibility. For
example, the 'nixops' flake depends on the 'nixops-aws' and
'nixops-hetzner' repositories. So when the 'nixops' flake is used in
another flake, we want the versions of 'nixops-aws' and
'nixops-hetzner' locked by the the 'nixops' flake because those
presumably have been tested.
This can lead to a proliferation of versions of flakes like 'nixpkgs'
(since every flake's lock file could depend on a different version of
'nixpkgs'). This is not a major issue when using Nixpkgs overlays or
NixOS modules, since then the top-level flake composes those
overlays/modules into *its* version of Nixpkgs and all other versions
are ignored. Lock file computation has been made a bit more lazy so it
won't try to fetch all those versions of 'nixpkgs'.
However, in case it's necessary to minimize flake versions, there now
are two input attributes that allow this. First, you can copy an input
from another flake, as follows:
inputs.nixpkgs.follows = "dwarffs/nixpkgs";
This states that the calling flake's 'nixpkgs' input shall be the same
as the 'nixpkgs' input of the 'dwarffs' input.
Second, you can override inputs of inputs:
inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
inputs.nixops.inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
or equivalently, using 'follows':
inputs.nixpkgs.url = github:edolstra/nixpkgs/<hash>;
inputs.nixops.inputs.nixpkgs.follows = "nixpkgs";
This states that the 'nixpkgs' input of the 'nixops' input shall be
the same as the calling flake's 'nixpkgs' input.
Finally, at '-v' Nix now prints the changes to the lock file, e.g.
$ nix flake update ~/Misc/eelco-configurations/hagbard
inputs of flake 'git+file:///home/eelco/Misc/eelco-configurations?subdir=hagbard' changed:
updated 'nixpkgs': 'github:edolstra/nixpkgs/7845bf5f4b3013df1cf036e9c9c3a55a30331db9' -> 'github:edolstra/nixpkgs/03f3def66a104a221aac8b751eeb7075374848fd'
removed 'nixops'
removed 'nixops/nixops-aws'
removed 'nixops/nixops-hetzner'
removed 'nixops/nixpkgs'
2020-01-24 23:05:11 +02:00
|
|
|
|
2020-06-12 00:34:02 +03:00
|
|
|
auto diff = LockFile::diff(oldLockFile, newLockFile);
|
2020-02-05 15:48:49 +02:00
|
|
|
|
2020-01-29 22:01:34 +02:00
|
|
|
if (lockFlags.writeLockFile) {
|
Remove TreeInfo
The attributes previously stored in TreeInfo (narHash, revCount,
lastModified) are now stored in Input. This makes it less arbitrary
what attributes are stored where.
As a result, the lock file format has changed. An entry like
"info": {
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github"
},
is now stored as
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github",
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
The 'Input' class is now a dumb set of attributes. All the fetcher
implementations subclass InputScheme, not Input. This simplifies the
API.
Also, fix substitution of flake inputs. This was broken since lazy
flake fetching started using fetchTree internally.
2020-05-30 01:44:11 +03:00
|
|
|
if (auto sourcePath = topRef.input.getSourcePath()) {
|
2020-01-24 14:07:03 +02:00
|
|
|
if (!newLockFile.isImmutable()) {
|
2020-01-21 17:27:53 +02:00
|
|
|
if (settings.warnDirty)
|
|
|
|
warn("will not write lock file of flake '%s' because it has a mutable input", topRef);
|
2019-09-20 15:29:49 +03:00
|
|
|
} else {
|
2020-01-29 22:01:34 +02:00
|
|
|
if (!lockFlags.updateLockFile)
|
|
|
|
throw Error("flake '%s' requires lock file changes but they're not allowed due to '--no-update-lock-file'", topRef);
|
|
|
|
|
2020-02-05 16:31:16 +02:00
|
|
|
auto relPath = (topRef.subdir == "" ? "" : topRef.subdir + "/") + "flake.lock";
|
|
|
|
|
|
|
|
auto path = *sourcePath + "/" + relPath;
|
2020-01-27 14:45:49 +02:00
|
|
|
|
2020-02-05 15:48:49 +02:00
|
|
|
bool lockFileExists = pathExists(path);
|
|
|
|
|
2020-06-11 15:40:21 +03:00
|
|
|
if (lockFileExists) {
|
|
|
|
auto s = chomp(diff);
|
|
|
|
if (s.empty())
|
|
|
|
warn("updating lock file '%s'", path);
|
|
|
|
else
|
|
|
|
warn("updating lock file '%s':\n%s", path, s);
|
|
|
|
} else
|
2020-01-27 14:45:49 +02:00
|
|
|
warn("creating lock file '%s'", path);
|
|
|
|
|
|
|
|
newLockFile.write(path);
|
2020-01-21 17:27:53 +02:00
|
|
|
|
Remove TreeInfo
The attributes previously stored in TreeInfo (narHash, revCount,
lastModified) are now stored in Input. This makes it less arbitrary
what attributes are stored where.
As a result, the lock file format has changed. An entry like
"info": {
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github"
},
is now stored as
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github",
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
The 'Input' class is now a dumb set of attributes. All the fetcher
implementations subclass InputScheme, not Input. This simplifies the
API.
Also, fix substitution of flake inputs. This was broken since lazy
flake fetching started using fetchTree internally.
2020-05-30 01:44:11 +03:00
|
|
|
topRef.input.markChangedFile(
|
2020-02-05 15:48:49 +02:00
|
|
|
(topRef.subdir == "" ? "" : topRef.subdir + "/") + "flake.lock",
|
|
|
|
lockFlags.commitLockFile
|
2020-02-05 16:31:16 +02:00
|
|
|
? std::optional<std::string>(fmt("%s: %s\n\nFlake input changes:\n\n%s",
|
|
|
|
relPath, lockFileExists ? "Update" : "Add", diff))
|
2020-02-05 15:48:49 +02:00
|
|
|
: std::nullopt);
|
2020-02-02 17:32:46 +02:00
|
|
|
|
|
|
|
/* Rewriting the lockfile changed the top-level
|
|
|
|
repo, so we should re-read it. FIXME: we could
|
|
|
|
also just clear the 'rev' field... */
|
|
|
|
auto prevLockedRef = flake.lockedRef;
|
2020-02-02 16:46:30 +02:00
|
|
|
FlakeCache dummyCache;
|
Remove TreeInfo
The attributes previously stored in TreeInfo (narHash, revCount,
lastModified) are now stored in Input. This makes it less arbitrary
what attributes are stored where.
As a result, the lock file format has changed. An entry like
"info": {
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github"
},
is now stored as
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github",
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
The 'Input' class is now a dumb set of attributes. All the fetcher
implementations subclass InputScheme, not Input. This simplifies the
API.
Also, fix substitution of flake inputs. This was broken since lazy
flake fetching started using fetchTree internally.
2020-05-30 01:44:11 +03:00
|
|
|
flake = getFlake(state, topRef, lockFlags.useRegistries, dummyCache);
|
2020-02-02 16:46:30 +02:00
|
|
|
|
2020-02-05 16:47:11 +02:00
|
|
|
if (lockFlags.commitLockFile &&
|
Remove TreeInfo
The attributes previously stored in TreeInfo (narHash, revCount,
lastModified) are now stored in Input. This makes it less arbitrary
what attributes are stored where.
As a result, the lock file format has changed. An entry like
"info": {
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github"
},
is now stored as
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github",
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
The 'Input' class is now a dumb set of attributes. All the fetcher
implementations subclass InputScheme, not Input. This simplifies the
API.
Also, fix substitution of flake inputs. This was broken since lazy
flake fetching started using fetchTree internally.
2020-05-30 01:44:11 +03:00
|
|
|
flake.lockedRef.input.getRev() &&
|
|
|
|
prevLockedRef.input.getRev() != flake.lockedRef.input.getRev())
|
|
|
|
warn("committed new revision '%s'", flake.lockedRef.input.getRev()->gitRev());
|
2020-02-05 16:47:11 +02:00
|
|
|
|
2020-02-02 17:32:46 +02:00
|
|
|
/* Make sure that we picked up the change,
|
|
|
|
i.e. the tree should usually be dirty
|
|
|
|
now. Corner case: we could have reverted from a
|
|
|
|
dirty to a clean tree! */
|
|
|
|
if (flake.lockedRef.input == prevLockedRef.input
|
Remove TreeInfo
The attributes previously stored in TreeInfo (narHash, revCount,
lastModified) are now stored in Input. This makes it less arbitrary
what attributes are stored where.
As a result, the lock file format has changed. An entry like
"info": {
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github"
},
is now stored as
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github",
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
The 'Input' class is now a dumb set of attributes. All the fetcher
implementations subclass InputScheme, not Input. This simplifies the
API.
Also, fix substitution of flake inputs. This was broken since lazy
flake fetching started using fetchTree internally.
2020-05-30 01:44:11 +03:00
|
|
|
&& !flake.lockedRef.input.isImmutable())
|
2020-02-02 16:46:30 +02:00
|
|
|
throw Error("'%s' did not change after I updated its 'flake.lock' file; is 'flake.lock' under version control?", flake.originalRef);
|
2019-07-12 14:29:54 +03:00
|
|
|
}
|
2019-05-21 16:03:54 +03:00
|
|
|
} else
|
2020-01-29 22:01:34 +02:00
|
|
|
throw Error("cannot write modified lock file of flake '%s' (use '--no-write-lock-file' to ignore)", topRef);
|
|
|
|
} else
|
2020-06-10 16:22:12 +03:00
|
|
|
warn("not writing modified lock file of flake '%s':\n%s", topRef, chomp(diff));
|
2019-05-21 15:55:43 +03:00
|
|
|
}
|
2018-11-29 20:18:36 +02:00
|
|
|
|
2020-01-24 14:07:03 +02:00
|
|
|
return LockedFlake { .flake = std::move(flake), .lockFile = std::move(newLockFile) };
|
2019-02-21 07:53:01 +02:00
|
|
|
}
|
|
|
|
|
2019-06-04 20:10:35 +03:00
|
|
|
void callFlake(EvalState & state,
|
2020-03-12 23:06:57 +02:00
|
|
|
const LockedFlake & lockedFlake,
|
2020-03-09 16:28:41 +02:00
|
|
|
Value & vRes)
|
2018-11-29 20:18:36 +02:00
|
|
|
{
|
2020-03-09 16:28:41 +02:00
|
|
|
auto vLocks = state.allocValue();
|
|
|
|
auto vRootSrc = state.allocValue();
|
2020-03-10 20:21:47 +02:00
|
|
|
auto vRootSubdir = state.allocValue();
|
|
|
|
auto vTmp1 = state.allocValue();
|
|
|
|
auto vTmp2 = state.allocValue();
|
2019-06-04 23:35:43 +03:00
|
|
|
|
2020-03-12 23:06:57 +02:00
|
|
|
mkString(*vLocks, lockedFlake.lockFile.to_string());
|
2019-08-30 14:06:23 +03:00
|
|
|
|
2020-03-12 23:06:57 +02:00
|
|
|
emitTreeAttrs(state, *lockedFlake.flake.sourceInfo, lockedFlake.flake.lockedRef.input, *vRootSrc);
|
2019-10-02 23:08:19 +03:00
|
|
|
|
2020-03-12 23:06:57 +02:00
|
|
|
mkString(*vRootSubdir, lockedFlake.flake.lockedRef.subdir);
|
2020-03-10 20:21:47 +02:00
|
|
|
|
2020-04-16 17:54:34 +03:00
|
|
|
static RootValue vCallFlake = nullptr;
|
2020-03-11 17:34:46 +02:00
|
|
|
|
|
|
|
if (!vCallFlake) {
|
2020-04-16 17:54:34 +03:00
|
|
|
vCallFlake = allocRootValue(state.allocValue());
|
2020-03-11 17:34:46 +02:00
|
|
|
state.eval(state.parseExprFromString(
|
|
|
|
#include "call-flake.nix.gen.hh"
|
2020-04-16 17:54:34 +03:00
|
|
|
, "/"), **vCallFlake);
|
2020-03-11 17:34:46 +02:00
|
|
|
}
|
|
|
|
|
2020-04-16 17:54:34 +03:00
|
|
|
state.callFunction(**vCallFlake, *vLocks, *vTmp1, noPos);
|
2020-03-10 20:21:47 +02:00
|
|
|
state.callFunction(*vTmp1, *vRootSrc, *vTmp2, noPos);
|
|
|
|
state.callFunction(*vTmp2, *vRootSubdir, vRes, noPos);
|
2019-04-16 14:56:08 +03:00
|
|
|
}
|
2019-02-12 22:55:43 +02:00
|
|
|
|
|
|
|
static void prim_getFlake(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
|
|
|
{
|
2020-04-03 14:07:05 +03:00
|
|
|
auto flakeRefS = state.forceStringNoCtx(*args[0], pos);
|
2020-04-27 23:53:11 +03:00
|
|
|
auto flakeRef = parseFlakeRef(flakeRefS, {}, true);
|
Remove TreeInfo
The attributes previously stored in TreeInfo (narHash, revCount,
lastModified) are now stored in Input. This makes it less arbitrary
what attributes are stored where.
As a result, the lock file format has changed. An entry like
"info": {
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github"
},
is now stored as
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github",
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
The 'Input' class is now a dumb set of attributes. All the fetcher
implementations subclass InputScheme, not Input. This simplifies the
API.
Also, fix substitution of flake inputs. This was broken since lazy
flake fetching started using fetchTree internally.
2020-05-30 01:44:11 +03:00
|
|
|
if (evalSettings.pureEval && !flakeRef.input.isImmutable())
|
2020-04-03 14:07:05 +03:00
|
|
|
throw Error("cannot call 'getFlake' on mutable flake reference '%s', at %s (use --impure to override)", flakeRefS, pos);
|
|
|
|
|
2020-01-29 22:01:34 +02:00
|
|
|
callFlake(state,
|
2020-04-03 14:07:05 +03:00
|
|
|
lockFlake(state, flakeRef,
|
2020-01-29 22:01:34 +02:00
|
|
|
LockFlags {
|
|
|
|
.updateLockFile = false,
|
|
|
|
.useRegistries = !evalSettings.pureEval,
|
|
|
|
.allowMutable = !evalSettings.pureEval,
|
|
|
|
}),
|
|
|
|
v);
|
2018-11-29 20:18:36 +02:00
|
|
|
}
|
|
|
|
|
2020-06-17 18:05:08 +03:00
|
|
|
static RegisterPrimOp r2("__getFlake", 1, prim_getFlake, "flakes");
|
2018-11-29 20:18:36 +02:00
|
|
|
|
2019-05-29 16:31:07 +03:00
|
|
|
}
|
|
|
|
|
2020-01-22 21:59:59 +02:00
|
|
|
Fingerprint LockedFlake::getFingerprint() const
|
2019-06-07 23:25:48 +03:00
|
|
|
{
|
2019-07-12 14:29:54 +03:00
|
|
|
// FIXME: as an optimization, if the flake contains a lock file
|
|
|
|
// and we haven't changed it, then it's sufficient to use
|
2019-06-07 23:25:48 +03:00
|
|
|
// flake.sourceInfo.storePath for the fingerprint.
|
|
|
|
return hashString(htSHA256,
|
2019-11-06 13:01:37 +02:00
|
|
|
fmt("%s;%d;%d;%s",
|
2020-01-21 17:27:53 +02:00
|
|
|
flake.sourceInfo->storePath.to_string(),
|
Remove TreeInfo
The attributes previously stored in TreeInfo (narHash, revCount,
lastModified) are now stored in Input. This makes it less arbitrary
what attributes are stored where.
As a result, the lock file format has changed. An entry like
"info": {
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github"
},
is now stored as
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github",
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
The 'Input' class is now a dumb set of attributes. All the fetcher
implementations subclass InputScheme, not Input. This simplifies the
API.
Also, fix substitution of flake inputs. This was broken since lazy
flake fetching started using fetchTree internally.
2020-05-30 01:44:11 +03:00
|
|
|
flake.lockedRef.input.getRevCount().value_or(0),
|
|
|
|
flake.lockedRef.input.getLastModified().value_or(0),
|
2019-11-06 13:01:37 +02:00
|
|
|
lockFile));
|
2019-06-07 23:25:48 +03:00
|
|
|
}
|
|
|
|
|
2020-01-21 17:27:53 +02:00
|
|
|
Flake::~Flake() { }
|
|
|
|
|
2019-05-29 16:31:07 +03:00
|
|
|
}
|