2017-11-01 17:32:53 +02:00
|
|
|
#include "primops.hh"
|
|
|
|
#include "eval-inline.hh"
|
|
|
|
#include "store-api.hh"
|
2020-03-30 17:04:18 +03:00
|
|
|
#include "fetchers.hh"
|
|
|
|
#include "url.hh"
|
2020-09-21 19:22:45 +03:00
|
|
|
#include "url-parts.hh"
|
2017-11-01 17:32:53 +02:00
|
|
|
|
|
|
|
namespace nix {
|
|
|
|
|
2022-03-04 20:31:59 +02:00
|
|
|
static void prim_fetchMercurial(EvalState & state, const PosIdx pos, Value * * args, Value & v)
|
2017-11-01 17:32:53 +02:00
|
|
|
{
|
|
|
|
std::string url;
|
2020-03-30 17:04:18 +03:00
|
|
|
std::optional<Hash> rev;
|
|
|
|
std::optional<std::string> ref;
|
2022-01-21 15:44:00 +02:00
|
|
|
std::string_view name = "source";
|
2017-11-01 17:32:53 +02:00
|
|
|
PathSet context;
|
|
|
|
|
2021-10-15 07:23:04 +03:00
|
|
|
state.forceValue(*args[0], pos);
|
2017-11-01 17:32:53 +02:00
|
|
|
|
2020-12-17 15:45:45 +02:00
|
|
|
if (args[0]->type() == nAttrs) {
|
2017-11-01 17:32:53 +02:00
|
|
|
|
|
|
|
for (auto & attr : *args[0]->attrs) {
|
2022-03-05 15:40:24 +02:00
|
|
|
std::string_view n(state.symbols[attr.name]);
|
2017-11-01 17:32:53 +02:00
|
|
|
if (n == "url")
|
2022-11-29 01:25:36 +02:00
|
|
|
url = state.coerceToString(attr.pos, *attr.value, context,
|
|
|
|
"while evaluating the `url` attribute passed to builtins.fetchMercurial",
|
|
|
|
false, false).toOwned();
|
2020-03-30 17:04:18 +03:00
|
|
|
else if (n == "rev") {
|
|
|
|
// Ugly: unlike fetchGit, here the "rev" attribute can
|
|
|
|
// be both a revision or a branch/tag name.
|
2023-01-19 14:23:04 +02:00
|
|
|
auto value = state.forceStringNoCtx(*attr.value, attr.pos, "while evaluating the `rev` attribute passed to builtins.fetchMercurial");
|
2022-01-21 15:44:00 +02:00
|
|
|
if (std::regex_match(value.begin(), value.end(), revRegex))
|
2020-07-02 01:34:18 +03:00
|
|
|
rev = Hash::parseAny(value, htSHA1);
|
2020-03-30 17:04:18 +03:00
|
|
|
else
|
|
|
|
ref = value;
|
|
|
|
}
|
2017-11-01 17:32:53 +02:00
|
|
|
else if (n == "name")
|
2023-01-19 14:23:04 +02:00
|
|
|
name = state.forceStringNoCtx(*attr.value, attr.pos, "while evaluating the `name` attribute passed to builtins.fetchMercurial");
|
2017-11-01 17:32:53 +02:00
|
|
|
else
|
2020-06-15 15:06:58 +03:00
|
|
|
throw EvalError({
|
2022-03-05 15:40:24 +02:00
|
|
|
.msg = hintfmt("unsupported argument '%s' to 'fetchMercurial'", state.symbols[attr.name]),
|
2022-03-04 20:31:59 +02:00
|
|
|
.errPos = state.positions[attr.pos]
|
2020-06-15 15:06:58 +03:00
|
|
|
});
|
2017-11-01 17:32:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (url.empty())
|
2020-06-15 15:06:58 +03:00
|
|
|
throw EvalError({
|
2021-01-21 01:27:36 +02:00
|
|
|
.msg = hintfmt("'url' argument required"),
|
2022-03-04 20:31:59 +02:00
|
|
|
.errPos = state.positions[pos]
|
2020-06-15 15:06:58 +03:00
|
|
|
});
|
2017-11-01 17:32:53 +02:00
|
|
|
|
|
|
|
} else
|
2022-11-29 01:25:36 +02:00
|
|
|
url = state.coerceToString(pos, *args[0], context,
|
|
|
|
"while evaluating the first argument passed to builtins.fetchMercurial",
|
|
|
|
false, false).toOwned();
|
2017-11-01 17:32:53 +02:00
|
|
|
|
|
|
|
// FIXME: git externals probably can be used to bypass the URI
|
|
|
|
// whitelist. Ah well.
|
|
|
|
state.checkURI(url);
|
|
|
|
|
2020-03-30 17:04:18 +03:00
|
|
|
if (evalSettings.pureEval && !rev)
|
|
|
|
throw Error("in pure evaluation mode, 'fetchMercurial' requires a Mercurial revision");
|
|
|
|
|
2020-04-07 15:00:12 +03:00
|
|
|
fetchers::Attrs attrs;
|
|
|
|
attrs.insert_or_assign("type", "hg");
|
|
|
|
attrs.insert_or_assign("url", url.find("://") != std::string::npos ? url : "file://" + url);
|
2022-02-25 17:00:00 +02:00
|
|
|
attrs.insert_or_assign("name", std::string(name));
|
2020-04-07 15:00:12 +03:00
|
|
|
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-30 01:44:11 +03:00
|
|
|
auto input = fetchers::Input::fromAttrs(std::move(attrs));
|
2020-03-30 17:04:18 +03:00
|
|
|
|
2020-04-07 15:00:12 +03: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-30 01:44:11 +03:00
|
|
|
auto [tree, input2] = input.fetch(state.store);
|
2017-11-01 17:32:53 +02:00
|
|
|
|
2022-01-04 18:39:16 +02:00
|
|
|
auto attrs2 = state.buildBindings(8);
|
2020-03-30 17:04:18 +03:00
|
|
|
auto storePath = state.store->printStorePath(tree.storePath);
|
2022-01-04 18:39:16 +02:00
|
|
|
attrs2.alloc(state.sOutPath).mkString(storePath, {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-30 01:44:11 +03:00
|
|
|
if (input2.getRef())
|
2022-01-04 18:39:16 +02:00
|
|
|
attrs2.alloc("branch").mkString(*input2.getRef());
|
2020-03-30 17:04:18 +03: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-30 01:44:11 +03:00
|
|
|
auto rev2 = input2.getRev().value_or(Hash(htSHA1));
|
2022-01-04 18:39:16 +02:00
|
|
|
attrs2.alloc("rev").mkString(rev2.gitRev());
|
|
|
|
attrs2.alloc("shortRev").mkString(rev2.gitRev().substr(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-30 01:44:11 +03:00
|
|
|
if (auto revCount = input2.getRevCount())
|
2022-01-04 18:39:16 +02:00
|
|
|
attrs2.alloc("revCount").mkInt(*revCount);
|
|
|
|
v.mkAttrs(attrs2);
|
2018-01-16 19:50:38 +02:00
|
|
|
|
2021-10-07 15:07:51 +03:00
|
|
|
state.allowPath(tree.storePath);
|
2017-11-01 17:32:53 +02:00
|
|
|
}
|
|
|
|
|
2020-10-06 14:36:55 +03:00
|
|
|
static RegisterPrimOp r_fetchMercurial("fetchMercurial", 1, prim_fetchMercurial);
|
2017-11-01 17:32:53 +02:00
|
|
|
|
|
|
|
}
|