2017-11-01 15:32:53 +00:00
|
|
|
#include "primops.hh"
|
|
|
|
#include "eval-inline.hh"
|
|
|
|
#include "store-api.hh"
|
2020-03-30 14:04:18 +00:00
|
|
|
#include "fetchers.hh"
|
|
|
|
#include "url.hh"
|
2017-11-01 15:32:53 +00:00
|
|
|
|
|
|
|
#include <regex>
|
|
|
|
|
|
|
|
namespace nix {
|
|
|
|
|
|
|
|
static void prim_fetchMercurial(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
|
|
|
{
|
|
|
|
std::string url;
|
2020-03-30 14:04:18 +00:00
|
|
|
std::optional<Hash> rev;
|
|
|
|
std::optional<std::string> ref;
|
2017-11-01 15:32:53 +00:00
|
|
|
std::string name = "source";
|
|
|
|
PathSet context;
|
|
|
|
|
|
|
|
state.forceValue(*args[0]);
|
|
|
|
|
|
|
|
if (args[0]->type == tAttrs) {
|
|
|
|
|
|
|
|
state.forceAttrs(*args[0], pos);
|
|
|
|
|
|
|
|
for (auto & attr : *args[0]->attrs) {
|
|
|
|
string n(attr.name);
|
|
|
|
if (n == "url")
|
|
|
|
url = state.coerceToString(*attr.pos, *attr.value, context, false, false);
|
2020-03-30 14:04:18 +00:00
|
|
|
else if (n == "rev") {
|
|
|
|
// Ugly: unlike fetchGit, here the "rev" attribute can
|
|
|
|
// be both a revision or a branch/tag name.
|
|
|
|
auto value = state.forceStringNoCtx(*attr.value, *attr.pos);
|
|
|
|
if (std::regex_match(value, revRegex))
|
|
|
|
rev = Hash(value, htSHA1);
|
|
|
|
else
|
|
|
|
ref = value;
|
|
|
|
}
|
2017-11-01 15:32:53 +00:00
|
|
|
else if (n == "name")
|
|
|
|
name = state.forceStringNoCtx(*attr.value, *attr.pos);
|
|
|
|
else
|
2020-06-15 12:06:58 +00:00
|
|
|
throw EvalError({
|
|
|
|
.hint = hintfmt("unsupported argument '%s' to 'fetchMercurial'", attr.name),
|
2020-06-23 21:30:13 +00:00
|
|
|
.errPos = *attr.pos
|
2020-06-15 12:06:58 +00:00
|
|
|
});
|
2017-11-01 15:32:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (url.empty())
|
2020-06-15 12:06:58 +00:00
|
|
|
throw EvalError({
|
|
|
|
.hint = hintfmt("'url' argument required"),
|
2020-06-23 21:30:13 +00:00
|
|
|
.errPos = pos
|
2020-06-15 12:06:58 +00:00
|
|
|
});
|
2017-11-01 15:32:53 +00:00
|
|
|
|
|
|
|
} else
|
|
|
|
url = state.coerceToString(pos, *args[0], context, false, false);
|
|
|
|
|
|
|
|
// FIXME: git externals probably can be used to bypass the URI
|
|
|
|
// whitelist. Ah well.
|
|
|
|
state.checkURI(url);
|
|
|
|
|
2020-03-30 14:04:18 +00:00
|
|
|
if (evalSettings.pureEval && !rev)
|
|
|
|
throw Error("in pure evaluation mode, 'fetchMercurial' requires a Mercurial revision");
|
|
|
|
|
2020-04-07 12:00:12 +00:00
|
|
|
fetchers::Attrs attrs;
|
|
|
|
attrs.insert_or_assign("type", "hg");
|
|
|
|
attrs.insert_or_assign("url", url.find("://") != std::string::npos ? url : "file://" + url);
|
|
|
|
if (ref) attrs.insert_or_assign("ref", *ref);
|
|
|
|
if (rev) attrs.insert_or_assign("rev", rev->gitRev());
|
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-29 22:44:11 +00:00
|
|
|
auto input = fetchers::Input::fromAttrs(std::move(attrs));
|
2020-03-30 14:04:18 +00:00
|
|
|
|
2020-04-07 12:00:12 +00:00
|
|
|
// FIXME: use name
|
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-29 22:44:11 +00:00
|
|
|
auto [tree, input2] = input.fetch(state.store);
|
2017-11-01 15:32:53 +00:00
|
|
|
|
|
|
|
state.mkAttrs(v, 8);
|
2020-03-30 14:04:18 +00:00
|
|
|
auto storePath = state.store->printStorePath(tree.storePath);
|
|
|
|
mkString(*state.allocAttr(v, state.sOutPath), storePath, PathSet({storePath}));
|
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-29 22:44:11 +00:00
|
|
|
if (input2.getRef())
|
|
|
|
mkString(*state.allocAttr(v, state.symbols.create("branch")), *input2.getRef());
|
2020-03-30 14:04:18 +00:00
|
|
|
// Backward compatibility: set 'rev' to
|
|
|
|
// 0000000000000000000000000000000000000000 for a dirty tree.
|
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-29 22:44:11 +00:00
|
|
|
auto rev2 = input2.getRev().value_or(Hash(htSHA1));
|
2020-03-30 14:04:18 +00:00
|
|
|
mkString(*state.allocAttr(v, state.symbols.create("rev")), rev2.gitRev());
|
|
|
|
mkString(*state.allocAttr(v, state.symbols.create("shortRev")), std::string(rev2.gitRev(), 0, 12));
|
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-29 22:44:11 +00:00
|
|
|
if (auto revCount = input2.getRevCount())
|
|
|
|
mkInt(*state.allocAttr(v, state.symbols.create("revCount")), *revCount);
|
2017-11-01 15:32:53 +00:00
|
|
|
v.attrs->sort();
|
2018-01-16 17:50:38 +00:00
|
|
|
|
|
|
|
if (state.allowedPaths)
|
2020-03-30 14:04:18 +00:00
|
|
|
state.allowedPaths->insert(tree.actualPath);
|
2017-11-01 15:32:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static RegisterPrimOp r("fetchMercurial", 1, prim_fetchMercurial);
|
|
|
|
|
|
|
|
}
|