Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: NixOS/nix
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 6cf91d6fbd65
Choose a base ref
...
head repository: NixOS/nix
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 485a87f22f96
Choose a head ref
  • 6 commits
  • 13 files changed
  • 1 contributor

Commits on Apr 2, 2020

  1. Move parseTreeInfo()

    edolstra committed Apr 2, 2020
    Copy the full SHA
    6d6467d View commit details
  2. Change lastModified to the number of seconds in the epoch

    'lastModifiedDate' is now a string representing the equivalent
    date/time.
    edolstra committed Apr 2, 2020
    Copy the full SHA
    ab47868 View commit details
  3. Improve error message

    edolstra committed Apr 2, 2020
    Copy the full SHA
    e1fc9f6 View commit details
  4. PathInput: Add some methods

    edolstra committed Apr 2, 2020
    Copy the full SHA
    78ad5b3 View commit details
  5. Respect the narHash attribute in more input types

    call-flake.nix now passes node.info.narHash to fetchTree. This ensures
    that dirty Git trees work even in pure mode.
    edolstra committed Apr 2, 2020
    Copy the full SHA
    a6ff66b View commit details
  6. Copy the full SHA
    485a87f View commit details
2 changes: 1 addition & 1 deletion flake.nix
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@
versionSuffix =
if officialRelease
then ""
else "pre${builtins.substring 0 8 self.lastModified}_${self.shortRev or "dirty"}";
else "pre${builtins.substring 0 8 self.lastModifiedDate}_${self.shortRev or "dirty"}";

officialRelease = false;

5 changes: 4 additions & 1 deletion src/libexpr/flake/call-flake.nix
Original file line number Diff line number Diff line change
@@ -8,7 +8,10 @@ let
builtins.mapAttrs
(key: node:
let
sourceInfo = if key == lockFile.root then rootSrc else fetchTree (removeAttrs node.locked ["dir"]);
sourceInfo =
if key == lockFile.root
then rootSrc
else fetchTree ({ inherit (node.info) narHash; } // removeAttrs node.locked ["dir"]);
subdir = if key == lockFile.root then rootSubdir else node.locked.dir or "";
flake = import (sourceInfo + (if subdir != "" then "/" else "") + subdir + "/flake.nix");
inputs = builtins.mapAttrs (inputName: key: allNodes.${key}) (node.inputs or {});
36 changes: 1 addition & 35 deletions src/libexpr/flake/lockfile.cc
Original file line number Diff line number Diff line change
@@ -32,44 +32,10 @@ FlakeRef getFlakeRef(
throw Error("attribute '%s' missing in lock file", version4Attr);
}

static TreeInfo parseTreeInfo(const nlohmann::json & json)
{
TreeInfo info;

auto i = json.find("info");
if (i != json.end()) {
const nlohmann::json & i2(*i);

auto j = i2.find("narHash");
if (j != i2.end())
info.narHash = Hash((std::string) *j);
else
throw Error("attribute 'narHash' missing in lock file");

j = i2.find("revCount");
if (j != i2.end())
info.revCount = *j;

j = i2.find("lastModified");
if (j != i2.end())
info.lastModified = *j;

return info;
}

i = json.find("narHash");
if (i != json.end()) {
info.narHash = Hash((std::string) *i);
return info;
}

throw Error("attribute 'info' missing in lock file");
}

LockedNode::LockedNode(const nlohmann::json & json)
: lockedRef(getFlakeRef(json, "url", "uri", "locked"))
, originalRef(getFlakeRef(json, "originalUrl", "originalUri", "original"))
, info(parseTreeInfo(json))
, info(TreeInfo::fromJson(json))
, isFlake(json.find("flake") != json.end() ? (bool) json["flake"] : true)
{
if (!lockedRef.input->isImmutable())
8 changes: 5 additions & 3 deletions src/libexpr/primops/fetchTree.cc
Original file line number Diff line number Diff line change
@@ -34,9 +34,11 @@ void emitTreeAttrs(
if (tree.info.revCount)
mkInt(*state.allocAttr(v, state.symbols.create("revCount")), *tree.info.revCount);

if (tree.info.lastModified)
mkString(*state.allocAttr(v, state.symbols.create("lastModified")),
if (tree.info.lastModified) {
mkInt(*state.allocAttr(v, state.symbols.create("lastModified")), *tree.info.lastModified);
mkString(*state.allocAttr(v, state.symbols.create("lastModifiedDate")),
fmt("%s", std::put_time(std::gmtime(&*tree.info.lastModified), "%Y%m%d%H%M%S")));
}

v.attrs->sort();
}
@@ -79,7 +81,7 @@ static void prim_fetchTree(EvalState & state, const Pos & pos, Value * * args, V
input = lookupInRegistries(state.store, input).first;

if (evalSettings.pureEval && !input->isImmutable())
throw Error("in pure evaluation mode, 'fetchTree' requires an immutable input");
throw Error("in pure evaluation mode, 'fetchTree' requires an immutable input, at %s", pos);

// FIXME: use fetchOrSubstituteTree
auto [tree, input2] = input->fetchTree(state.store);
4 changes: 3 additions & 1 deletion src/libfetchers/fetchers.cc
Original file line number Diff line number Diff line change
@@ -29,8 +29,10 @@ std::unique_ptr<Input> inputFromURL(const std::string & url)

std::unique_ptr<Input> inputFromAttrs(const Attrs & attrs)
{
auto attrs2(attrs);
attrs2.erase("narHash");
for (auto & inputScheme : *inputSchemes) {
auto res = inputScheme->inputFromAttrs(attrs);
auto res = inputScheme->inputFromAttrs(attrs2);
if (res) {
if (auto narHash = maybeGetStrAttr(attrs, "narHash"))
// FIXME: require SRI hash.
2 changes: 1 addition & 1 deletion src/libfetchers/git.cc
Original file line number Diff line number Diff line change
@@ -39,7 +39,7 @@ struct GitInput : Input

bool isImmutable() const override
{
return (bool) rev;
return (bool) rev || narHash;
}

std::optional<std::string> getRef() const override { return ref; }
2 changes: 1 addition & 1 deletion src/libfetchers/github.cc
Original file line number Diff line number Diff line change
@@ -33,7 +33,7 @@ struct GitHubInput : Input

bool isImmutable() const override
{
return (bool) rev;
return (bool) rev || narHash;
}

std::optional<std::string> getRef() const override { return ref; }
2 changes: 1 addition & 1 deletion src/libfetchers/mercurial.cc
Original file line number Diff line number Diff line change
@@ -33,7 +33,7 @@ struct MercurialInput : Input

bool isImmutable() const override
{
return (bool) rev;
return (bool) rev || narHash;
}

std::optional<std::string> getRef() const override { return ref; }
16 changes: 16 additions & 0 deletions src/libfetchers/path.cc
Original file line number Diff line number Diff line change
@@ -19,6 +19,22 @@ struct PathInput : Input

std::optional<Hash> getRev() const override { return rev; }

bool operator ==(const Input & other) const override
{
auto other2 = dynamic_cast<const PathInput *>(&other);
return
other2
&& path == other2->path
&& rev == other2->rev
&& revCount == other2->revCount
&& lastModified == other2->lastModified;
}

bool isImmutable() const override
{
return (bool) narHash;
}

ParsedURL toURL() const override
{
auto query = attrsToQuery(toAttrsInternal());
73 changes: 39 additions & 34 deletions src/libfetchers/registry.cc
Original file line number Diff line number Diff line change
@@ -17,46 +17,51 @@ std::shared_ptr<Registry> Registry::read(
if (!pathExists(path))
return std::make_shared<Registry>(type);

auto json = nlohmann::json::parse(readFile(path));

auto version = json.value("version", 0);

// FIXME: remove soon
if (version == 1) {
auto flakes = json["flakes"];
for (auto i = flakes.begin(); i != flakes.end(); ++i) {
auto url = i->value("url", i->value("uri", ""));
if (url.empty())
throw Error("flake registry '%s' lacks a 'url' attribute for entry '%s'",
path, i.key());
registry->entries.push_back(
{inputFromURL(i.key()), inputFromURL(url), {}});
try {

auto json = nlohmann::json::parse(readFile(path));

auto version = json.value("version", 0);

// FIXME: remove soon
if (version == 1) {
auto flakes = json["flakes"];
for (auto i = flakes.begin(); i != flakes.end(); ++i) {
auto url = i->value("url", i->value("uri", ""));
if (url.empty())
throw Error("flake registry '%s' lacks a 'url' attribute for entry '%s'",
path, i.key());
registry->entries.push_back(
{inputFromURL(i.key()), inputFromURL(url), {}});
}
}
}

else if (version == 2) {
for (auto & i : json["flakes"]) {
auto toAttrs = jsonToAttrs(i["to"]);
Attrs extraAttrs;
auto j = toAttrs.find("dir");
if (j != toAttrs.end()) {
extraAttrs.insert(*j);
toAttrs.erase(j);
else if (version == 2) {
for (auto & i : json["flakes"]) {
auto toAttrs = jsonToAttrs(i["to"]);
Attrs extraAttrs;
auto j = toAttrs.find("dir");
if (j != toAttrs.end()) {
extraAttrs.insert(*j);
toAttrs.erase(j);
}
auto exact = i.find("exact");
registry->entries.push_back(
Entry {
.from = inputFromAttrs(jsonToAttrs(i["from"])),
.to = inputFromAttrs(toAttrs),
.extraAttrs = extraAttrs,
.exact = exact != i.end() && exact.value()
});
}
auto exact = i.find("exact");
registry->entries.push_back(
Entry {
.from = inputFromAttrs(jsonToAttrs(i["from"])),
.to = inputFromAttrs(toAttrs),
.extraAttrs = extraAttrs,
.exact = exact != i.end() && exact.value()
});
}
}

else
throw Error("flake registry '%s' has unsupported version %d", path, version);
else
throw Error("flake registry '%s' has unsupported version %d", path, version);

} catch (nlohmann::json::exception & e) {
warn("cannot parse flake registry '%s': %s", path, e.what());
}

return registry;
}
6 changes: 2 additions & 4 deletions src/libfetchers/tarball.cc
Original file line number Diff line number Diff line change
@@ -205,9 +205,7 @@ struct TarballInput : Input
{
Attrs attrs;
attrs.emplace("url", url.to_string());
if (narHash)
attrs.emplace("narHash", narHash->to_string(SRI));
else if (hash)
if (hash)
attrs.emplace("hash", hash->to_string(SRI));
return attrs;
}
@@ -260,7 +258,7 @@ struct TarballInputScheme : InputScheme
if (maybeGetStrAttr(attrs, "type") != "tarball") return {};

for (auto & [name, value] : attrs)
if (name != "type" && name != "url" && name != "hash" && name != "narHash")
if (name != "type" && name != "url" && name != "hash")
throw Error("unsupported tarball input attribute '%s'", name);

auto input = std::make_unique<TarballInput>(parseURL(getStrAttr(attrs, "url")));
34 changes: 34 additions & 0 deletions src/libfetchers/tree-info.cc
Original file line number Diff line number Diff line change
@@ -11,6 +11,40 @@ StorePath TreeInfo::computeStorePath(Store & store) const
return store.makeFixedOutputPath(true, narHash, "source");
}

TreeInfo TreeInfo::fromJson(const nlohmann::json & json)
{
TreeInfo info;

auto i = json.find("info");
if (i != json.end()) {
const nlohmann::json & i2(*i);

auto j = i2.find("narHash");
if (j != i2.end())
info.narHash = Hash((std::string) *j);
else
throw Error("attribute 'narHash' missing in lock file");

j = i2.find("revCount");
if (j != i2.end())
info.revCount = *j;

j = i2.find("lastModified");
if (j != i2.end())
info.lastModified = *j;

return info;
}

i = json.find("narHash");
if (i != json.end()) {
info.narHash = Hash((std::string) *i);
return info;
}

throw Error("attribute 'info' missing in lock file");
}

nlohmann::json TreeInfo::toJson() const
{
nlohmann::json json;
2 changes: 2 additions & 0 deletions src/libfetchers/tree-info.hh
Original file line number Diff line number Diff line change
@@ -25,6 +25,8 @@ struct TreeInfo

StorePath computeStorePath(Store & store) const;

static TreeInfo fromJson(const nlohmann::json & json);

nlohmann::json toJson() const;
};