* Magic attribute `exportReferencesGraph' that allows the references
graph to be passed to a builder. This attribute should be a list of pairs [name1 path1 name2 path2 ...]. The references graph of each `pathN' will be stored in a text file `nameN' in the temporary build directory. The text files have the format used by `nix-store --register-validity'. However, the deriver fields are left empty. `exportReferencesGraph' is useful for builders that want to do something with the closure of a store path. Examples: the builders that make initrds and ISO images for NixOS. `exportReferencesGraph' is entirely pure. It's necessary because otherwise the only way for a builder to get this information would be to call `nix-store' directly, which is not allowed (though unfortunately possible).
This commit is contained in:
parent
e40d4a5604
commit
e2a70b7ec0
3 changed files with 65 additions and 21 deletions
|
@ -30,8 +30,12 @@
|
||||||
<listitem><para>TODO: now using Berkeley DB 4.5.</para></listitem>
|
<listitem><para>TODO: now using Berkeley DB 4.5.</para></listitem>
|
||||||
|
|
||||||
|
|
||||||
<listitem><para>Option <option>--reregister</option> in
|
<listitem><para>TODO: option <option>--reregister</option> in
|
||||||
<command>nix-store --register-validity</command>.</para></listitem>
|
<command>nix-store --register-validity</command>.</para></listitem>
|
||||||
|
|
||||||
|
|
||||||
|
<listitem><para>TODO: magic <varname>exportReferencesGraph</varname>
|
||||||
|
attribute.</para></listitem>
|
||||||
|
|
||||||
|
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
|
|
|
@ -901,6 +901,34 @@ string showPaths(const PathSet & paths)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Return a string accepted by `nix-store --register-validity' that
|
||||||
|
registers the specified paths as valid. Note: it's the
|
||||||
|
responsibility of the caller to provide a closure. */
|
||||||
|
static string makeValidityRegistration(const PathSet & paths,
|
||||||
|
bool showDerivers)
|
||||||
|
{
|
||||||
|
string s = "";
|
||||||
|
|
||||||
|
for (PathSet::iterator i = paths.begin(); i != paths.end(); ++i) {
|
||||||
|
s += *i + "\n";
|
||||||
|
|
||||||
|
Path deriver = showDerivers ? queryDeriver(noTxn, *i) : "";
|
||||||
|
s += deriver + "\n";
|
||||||
|
|
||||||
|
PathSet references;
|
||||||
|
queryReferences(noTxn, *i, references);
|
||||||
|
|
||||||
|
s += (format("%1%\n") % references.size()).str();
|
||||||
|
|
||||||
|
for (PathSet::iterator j = references.begin();
|
||||||
|
j != references.end(); ++j)
|
||||||
|
s += *j + "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
DerivationGoal::HookReply DerivationGoal::tryBuildHook()
|
DerivationGoal::HookReply DerivationGoal::tryBuildHook()
|
||||||
{
|
{
|
||||||
Path buildHook = getEnv("NIX_BUILD_HOOK");
|
Path buildHook = getEnv("NIX_BUILD_HOOK");
|
||||||
|
@ -1024,26 +1052,8 @@ DerivationGoal::HookReply DerivationGoal::tryBuildHook()
|
||||||
|
|
||||||
/* The `references' file has exactly the format accepted by
|
/* The `references' file has exactly the format accepted by
|
||||||
`nix-store --register-validity'. */
|
`nix-store --register-validity'. */
|
||||||
s = "";
|
writeStringToFile(referencesFN,
|
||||||
for (PathSet::iterator i = allInputs.begin();
|
makeValidityRegistration(allInputs, true));
|
||||||
i != allInputs.end(); ++i)
|
|
||||||
{
|
|
||||||
s += *i + "\n";
|
|
||||||
|
|
||||||
Path deriver = queryDeriver(noTxn, *i);
|
|
||||||
s += deriver + "\n";
|
|
||||||
|
|
||||||
PathSet references;
|
|
||||||
queryReferences(noTxn, *i, references);
|
|
||||||
|
|
||||||
s += (format("%1%\n") % references.size()).str();
|
|
||||||
|
|
||||||
for (PathSet::iterator j = references.begin();
|
|
||||||
j != references.end(); ++j)
|
|
||||||
s += *j + "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
writeStringToFile(referencesFN, s);
|
|
||||||
|
|
||||||
/* Tell the hook to proceed. */
|
/* Tell the hook to proceed. */
|
||||||
writeLine(toHook.writeSide, "okay");
|
writeLine(toHook.writeSide, "okay");
|
||||||
|
@ -1235,6 +1245,32 @@ void DerivationGoal::startBuilder()
|
||||||
env[*i] = getEnv(*i);
|
env[*i] = getEnv(*i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The `exportReferencesGraph' feature allows the references graph
|
||||||
|
to be passed to a builder. This attribute should be a list of
|
||||||
|
pairs [name1 path1 name2 path2 ...]. The references graph of
|
||||||
|
each `pathN' will be stored in a text file `nameN' in the
|
||||||
|
temporary build directory. The text files have the format used
|
||||||
|
by `nix-store --register-validity'. However, the deriver
|
||||||
|
fields are left empty. */
|
||||||
|
string s = drv.env["exportReferencesGraph"];
|
||||||
|
Strings ss = tokenizeString(s);
|
||||||
|
if (ss.size() % 2 != 0)
|
||||||
|
throw Error(format("odd number of tokens in `exportReferencesGraph': `%1%'") % s);
|
||||||
|
for (Strings::iterator i = ss.begin(); i != ss.end(); ) {
|
||||||
|
string fileName = *i++;
|
||||||
|
Path storePath = *i++;
|
||||||
|
if (!isValidPath(storePath))
|
||||||
|
throw Error(format("`exportReferencesGraph' refers to an invalid path `%1%'")
|
||||||
|
% storePath);
|
||||||
|
checkStoreName(fileName); /* !!! abuse of this function */
|
||||||
|
PathSet refs;
|
||||||
|
computeFSClosure(storePath, refs);
|
||||||
|
/* !!! in secure Nix, the writing should be done on the
|
||||||
|
build uid for security (maybe). */
|
||||||
|
writeStringToFile(tmpDir + "/" + fileName,
|
||||||
|
makeValidityRegistration(refs, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* If we are running as root, and the `build-allow-root' setting
|
/* If we are running as root, and the `build-allow-root' setting
|
||||||
is `false', then we have to build as one of the users listed in
|
is `false', then we have to build as one of the users listed in
|
||||||
|
|
|
@ -259,6 +259,10 @@ Path toStorePath(const Path & path)
|
||||||
void checkStoreName(const string & name)
|
void checkStoreName(const string & name)
|
||||||
{
|
{
|
||||||
string validChars = "+-._?=";
|
string validChars = "+-._?=";
|
||||||
|
/* Disallow names starting with a dot for possible security
|
||||||
|
reasons (e.g., "." and ".."). */
|
||||||
|
if (string(name, 0, 1) == ".")
|
||||||
|
throw Error(format("illegal name: `%1%'") % name);
|
||||||
for (string::const_iterator i = name.begin(); i != name.end(); ++i)
|
for (string::const_iterator i = name.begin(); i != name.end(); ++i)
|
||||||
if (!((*i >= 'A' && *i <= 'Z') ||
|
if (!((*i >= 'A' && *i <= 'Z') ||
|
||||||
(*i >= 'a' && *i <= 'z') ||
|
(*i >= 'a' && *i <= 'z') ||
|
||||||
|
|
Loading…
Reference in a new issue