-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
/
patch.cc
125 lines (100 loc) · 3.9 KB
/
patch.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#include "primops.hh"
#include "patching-input-accessor.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, "while evaluating the first argument to 'builtins.patch'");
for (auto & attr : *args[0]->attrs()) {
std::string_view n(state.symbols[attr.name]);
auto check = [&]() {
if (!patches.empty())
state.error<EvalError>("'builtins.patch' does not support both 'patches' and 'patchFiles'")
.atPos(attr.pos)
.debugThrow();
};
if (n == "src") {
NixStringContext context;
src.emplace(state.coerceToPath(
pos, *attr.value, context, "while evaluating the 'src' attribute passed to 'builtins.patch'"));
}
else if (n == "patchFiles") {
check();
state.forceList(
*attr.value, attr.pos, "while evaluating the 'patchFiles' attribute passed to 'builtins.patch'");
for (auto elem : attr.value->listItems()) {
// FIXME: use realisePath
NixStringContext context;
auto patchFile = state.coerceToPath(
attr.pos, *elem, context, "while evaluating the 'patchFiles' attribute passed to 'builtins.patch'");
patches.push_back(patchFile.readFile());
}
}
else if (n == "patches") {
check();
auto err = "while evaluating the 'patches' attribute passed to 'builtins.patch'";
state.forceList(*attr.value, attr.pos, err);
for (auto elem : attr.value->listItems())
patches.push_back(std::string(state.forceStringNoCtx(*elem, attr.pos, err)));
}
else
state.error<EvalError>("attribute '%s' isn't supported in call to 'builtins.patch'", n)
.atPos(pos)
.debugThrow();
}
if (!src)
state.error<EvalError>("attribute 'src' is missing in call to 'builtins.patch'").atPos(pos).debugThrow();
if (!src->path.isRoot())
throw UnimplementedError("applying patches to a non-root path ('%s') is not yet supported", src->path);
auto accessor = makePatchingSourceAccessor(src->accessor, patches);
state.registerAccessor(accessor);
v.mkPath(SourcePath{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,
});
}