Skip to content

Commit

Permalink
Allow the 'url' flake input attribute to be a path literal
Browse files Browse the repository at this point in the history
  • Loading branch information
edolstra committed May 17, 2024
1 parent 49f592d commit 3180671
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 11 deletions.
34 changes: 25 additions & 9 deletions src/libexpr/flake/flake.cc
Original file line number Diff line number Diff line change
Expand Up @@ -96,14 +96,16 @@ static std::map<FlakeId, FlakeInput> parseFlakeInputs(
EvalState & state,
Value * value,
const PosIdx pos,
InputPath lockRootPath);
InputPath lockRootPath,
const SourcePath & flakeDir);

static FlakeInput parseFlakeInput(
EvalState & state,
const std::string & inputName,
Value * value,
const PosIdx pos,
InputPath lockRootPath)
InputPath lockRootPath,
const SourcePath & flakeDir)
{
expectType(state, nAttrs, *value, pos);

Expand All @@ -120,14 +122,25 @@ static FlakeInput parseFlakeInput(
for (auto & attr : *value->attrs()) {
try {
if (attr.name == sUrl) {
expectType(state, nString, *attr.value, attr.pos);
url = attr.value->string_view();
forceTrivialValue(state, *attr.value, pos);
if (attr.value->type() == nString)
url = attr.value->string_view();
else if (attr.value->type() == nPath) {
auto path = attr.value->path();
if (path.accessor != flakeDir.accessor)
throw Error("input path '%s' at %s must be in the same source tree as %s",
path, state.positions[attr.pos], flakeDir);
url = "path:" + flakeDir.path.makeRelative(path.path);
}
else
throw Error("expected a string or a path but got %s at %s",
showType(attr.value->type()), state.positions[attr.pos]);
attrs.emplace("url", *url);
} else if (attr.name == sFlake) {
expectType(state, nBool, *attr.value, attr.pos);
input.isFlake = attr.value->boolean();
} else if (attr.name == sInputs) {
input.overrides = parseFlakeInputs(state, attr.value, attr.pos, lockRootPath);
input.overrides = parseFlakeInputs(state, attr.value, attr.pos, lockRootPath, flakeDir);
} else if (attr.name == sFollows) {
expectType(state, nString, *attr.value, attr.pos);
auto follows(parseInputPath(attr.value->c_str()));
Expand Down Expand Up @@ -191,7 +204,8 @@ static std::map<FlakeId, FlakeInput> parseFlakeInputs(
EvalState & state,
Value * value,
const PosIdx pos,
InputPath lockRootPath)
InputPath lockRootPath,
const SourcePath & flakeDir)
{
std::map<FlakeId, FlakeInput> inputs;

Expand All @@ -203,7 +217,8 @@ static std::map<FlakeId, FlakeInput> parseFlakeInputs(
state.symbols[inputAttr.name],
inputAttr.value,
inputAttr.pos,
lockRootPath));
lockRootPath,
flakeDir));
}

return inputs;
Expand All @@ -217,7 +232,8 @@ static Flake readFlake(
const SourcePath & rootDir,
const InputPath & lockRootPath)
{
auto flakePath = rootDir / CanonPath(resolvedRef.subdir) / "flake.nix";
auto flakeDir = rootDir / CanonPath(resolvedRef.subdir);
auto flakePath = flakeDir / "flake.nix";

// NOTE evalFile forces vInfo to be an attrset because mustBeTrivial is true.
Value vInfo;
Expand All @@ -238,7 +254,7 @@ static Flake readFlake(
auto sInputs = state.symbols.create("inputs");

if (auto inputs = vInfo.attrs()->get(sInputs))
flake.inputs = parseFlakeInputs(state, inputs->value, inputs->pos, lockRootPath);
flake.inputs = parseFlakeInputs(state, inputs->value, inputs->pos, lockRootPath, flakeDir);

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

Expand Down
4 changes: 2 additions & 2 deletions tests/functional/flakes/relative-paths.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ mkdir -p $rootFlake $subflake0 $subflake1 $subflake2

cat > $rootFlake/flake.nix <<EOF
{
inputs.sub0.url = "./sub0";
inputs.sub0.url = ./sub0;
outputs = { self, sub0 }: {
x = 2;
y = self.x * sub0.x;
Expand Down Expand Up @@ -50,7 +50,7 @@ git -C $rootFlake add flake.nix sub0/flake.nix sub1/flake.nix

cat > $subflake2/flake.nix <<EOF
{
inputs.root.url = "../";
inputs.root.url = ./..;
inputs.sub1.url = "../sub1";
outputs = { self, root, sub1 }: {
x = 5;
Expand Down

0 comments on commit 3180671

Please sign in to comment.