mirror of
https://github.com/privatevoid-net/nix-super.git
synced 2024-11-28 08:36:15 +02:00
Add builtins.patch
This replaces the 'patches' argument to builtins.fetchTree with something more generic. So instead of 'builtins.fetchTree { patches = ... }' you can do 'builtins.patch { src = builtins.fetchTree { ... }; patchFiles = ... }'.
This commit is contained in:
parent
2b30df7b46
commit
5f1340219b
3 changed files with 125 additions and 20 deletions
|
@ -110,7 +110,6 @@ static void fetchTree(
|
|||
) {
|
||||
fetchers::Input input;
|
||||
PathSet context;
|
||||
std::vector<std::string> patches;
|
||||
|
||||
state.forceValue(*args[0], pos);
|
||||
|
||||
|
@ -137,19 +136,6 @@ static void fetchTree(
|
|||
for (auto & attr : *args[0]->attrs) {
|
||||
if (attr.name == state.sType) continue;
|
||||
|
||||
if (state.symbols[attr.name] == "patches") {
|
||||
state.forceList(*attr.value, attr.pos);
|
||||
|
||||
for (auto elem : attr.value->listItems()) {
|
||||
// FIXME: use realisePath
|
||||
PathSet context;
|
||||
auto patchFile = state.coerceToPath(pos, *elem, context);
|
||||
patches.push_back(patchFile.readFile());
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
state.forceValue(*attr.value, attr.pos);
|
||||
|
||||
if (attr.value->type() == nPath || attr.value->type() == nString) {
|
||||
|
@ -200,9 +186,6 @@ static void fetchTree(
|
|||
if (params.returnPath) {
|
||||
auto [accessor, input2] = input.lazyFetch(state.store);
|
||||
|
||||
if (!patches.empty())
|
||||
accessor = makePatchingInputAccessor(accessor, patches);
|
||||
|
||||
emitTreeAttrs(
|
||||
state,
|
||||
{ state.registerAccessor(accessor), CanonPath::root },
|
||||
|
@ -211,8 +194,6 @@ static void fetchTree(
|
|||
params.emptyRevFallback,
|
||||
false);
|
||||
} else {
|
||||
assert(patches.empty());
|
||||
|
||||
auto [tree, input2] = input.fetch(state.store);
|
||||
|
||||
auto storePath = state.store->printStorePath(tree.storePath);
|
||||
|
|
124
src/libexpr/primops/patch.cc
Normal file
124
src/libexpr/primops/patch.cc
Normal file
|
@ -0,0 +1,124 @@
|
|||
#include "primops.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
static void prim_patch(EvalState & state, const PosIdx pos, Value * * args, Value & v)
|
||||
{
|
||||
std::vector<std::string> patches;
|
||||
std::optional<SourcePath> src;
|
||||
|
||||
state.forceAttrs(*args[0], pos);
|
||||
|
||||
for (auto & attr : *args[0]->attrs) {
|
||||
std::string_view n(state.symbols[attr.name]);
|
||||
|
||||
auto check = [&]()
|
||||
{
|
||||
if (!patches.empty())
|
||||
state.debugThrowLastTrace(EvalError({
|
||||
.msg = hintfmt("'builtins.patch' does not support both 'patches' and 'patchFiles'"),
|
||||
.errPos = state.positions[attr.pos]
|
||||
}));
|
||||
};
|
||||
|
||||
if (n == "src") {
|
||||
PathSet context;
|
||||
src.emplace(state.coerceToPath(pos, *attr.value, context));
|
||||
}
|
||||
|
||||
else if (n == "patchFiles") {
|
||||
check();
|
||||
state.forceList(*attr.value, attr.pos);
|
||||
for (auto elem : attr.value->listItems()) {
|
||||
// FIXME: use realisePath
|
||||
PathSet context;
|
||||
auto patchFile = state.coerceToPath(attr.pos, *elem, context);
|
||||
patches.push_back(patchFile.readFile());
|
||||
}
|
||||
}
|
||||
|
||||
else if (n == "patches") {
|
||||
check();
|
||||
state.forceList(*attr.value, attr.pos);
|
||||
for (auto elem : attr.value->listItems())
|
||||
patches.push_back(std::string(state.forceStringNoCtx(*elem, attr.pos)));
|
||||
}
|
||||
|
||||
else
|
||||
throw Error({
|
||||
.msg = hintfmt("attribute '%s' isn't supported in call to 'builtins.patch'", n),
|
||||
.errPos = state.positions[pos]
|
||||
});
|
||||
}
|
||||
|
||||
if (!src)
|
||||
state.debugThrowLastTrace(EvalError({
|
||||
.msg = hintfmt("attribute 'src' is missing in call to 'builtins.patch'"),
|
||||
.errPos = state.positions[pos]
|
||||
}));
|
||||
|
||||
if (!src->path.isRoot())
|
||||
throw UnimplementedError("applying patches to a non-root path ('%s') is not yet supported", src->path);
|
||||
|
||||
auto accessor = makePatchingInputAccessor(ref(src->accessor.shared_from_this()), patches);
|
||||
|
||||
v.mkPath(SourcePath { state.registerAccessor(accessor), src->path });
|
||||
}
|
||||
|
||||
static RegisterPrimOp primop_patch({
|
||||
.name = "__patch",
|
||||
.args = {"args"},
|
||||
.doc = R"(
|
||||
Apply patches to a source tree. This function has the following required argument:
|
||||
|
||||
- src\
|
||||
The input source tree.
|
||||
|
||||
It also takes one of the following:
|
||||
|
||||
- patchFiles\
|
||||
A list of patch files to be applied to `src`.
|
||||
|
||||
- patches\
|
||||
A list of patches (i.e. strings) to be applied to `src`.
|
||||
|
||||
It returns a source tree that lazily and non-destructively
|
||||
applies the specified patches to `src`.
|
||||
|
||||
Example:
|
||||
|
||||
```nix
|
||||
let
|
||||
tree = builtins.patch {
|
||||
src = fetchTree {
|
||||
type = "github";
|
||||
owner = "NixOS";
|
||||
repo = "patchelf";
|
||||
rev = "be0cc30a59b2755844bcd48823f6fbc8d97b93a7";
|
||||
};
|
||||
patches = [
|
||||
''
|
||||
diff --git a/src/patchelf.cc b/src/patchelf.cc
|
||||
index 6882b28..28f511c 100644
|
||||
--- a/src/patchelf.cc
|
||||
+++ b/src/patchelf.cc
|
||||
@@ -1844,6 +1844,8 @@ void showHelp(const std::string & progName)
|
||||
|
||||
int mainWrapped(int argc, char * * argv)
|
||||
{
|
||||
+ printf("Hello!");
|
||||
+
|
||||
if (argc <= 1) {
|
||||
showHelp(argv[0]);
|
||||
return 1;
|
||||
|
||||
''
|
||||
];
|
||||
};
|
||||
in builtins.readFile (tree + "/src/patchelf.cc")
|
||||
```
|
||||
)",
|
||||
.fun = prim_patch,
|
||||
});
|
||||
|
||||
}
|
|
@ -9,7 +9,7 @@ namespace nix {
|
|||
|
||||
MakeError(RestrictedPathError, Error);
|
||||
|
||||
struct InputAccessor
|
||||
struct InputAccessor : public std::enable_shared_from_this<InputAccessor>
|
||||
{
|
||||
const size_t number;
|
||||
|
||||
|
|
Loading…
Reference in a new issue