From 54037f4e2d0045aacd044b714e4bf77d0924f249 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 31 Jan 2020 20:50:46 +0100 Subject: [PATCH] Allow flake input specification via attributes rather than a URL E.g. inputs.dwarffs = { type = "github"; owner = "edolstra"; repo = "dwarffs"; }; rather than inputs.dwarffs.url = github:edolstra/dwarffs; --- src/libexpr/flake/flake.cc | 56 +++++++++++++++++++++++++++----------- tests/flakes.sh | 5 +++- 2 files changed, 44 insertions(+), 17 deletions(-) diff --git a/src/libexpr/flake/flake.cc b/src/libexpr/flake/flake.cc index c40a903b9..be14c9af3 100644 --- a/src/libexpr/flake/flake.cc +++ b/src/libexpr/flake/flake.cc @@ -77,25 +77,49 @@ static FlakeInput parseFlakeInput(EvalState & state, auto sFlake = state.symbols.create("flake"); auto sFollows = state.symbols.create("follows"); + fetchers::Input::Attrs attrs; + std::optional url; + for (Attr attr : *(value->attrs)) { - if (attr.name == sUrl || attr.name == sUri) { - expectType(state, tString, *attr.value, *attr.pos); - input.ref = parseFlakeRef(attr.value->string.s); - } 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); - try { + try { + if (attr.name == sUrl || attr.name == sUri) { + 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); input.follows = parseInputPath(attr.value->string.s); - } catch (Error & e) { - e.addPrefix("in flake attribute at '%s':\n"); + } else { + state.forceValue(*attr.value); + if (attr.value->type == tString) + attrs.emplace(attr.name, attr.value->string.s); + else + throw Error("unsupported attribute type"); } - } else - throw Error("flake input '%s' has an unsupported attribute '%s', at %s", - inputName, attr.name, *attr.pos); + } catch (Error & e) { + e.addPrefix(fmt("in flake attribute '%s' at '%s':\n", attr.name, *attr.pos)); + throw; + } + } + + if (attrs.count("type")) + try { + input.ref = FlakeRef::fromAttrs(attrs); + } catch (Error & e) { + e.addPrefix(fmt("in flake input at '%s':\n", pos)); + throw; + } + else { + attrs.erase("url"); + if (!attrs.empty()) + throw Error("unexpected flake input attribute '%s', at %s", attrs.begin()->first, pos); + if (url) + input.ref = parseFlakeRef(*url); } return input; diff --git a/tests/flakes.sh b/tests/flakes.sh index 570f4f468..2e4abf48d 100644 --- a/tests/flakes.sh +++ b/tests/flakes.sh @@ -468,7 +468,10 @@ cat > $flake3Dir/flake.nix <