Merge "feat: Add temp-dir setting" into main
This commit is contained in:
commit
d0e0969810
13
doc/manual/rl-next/nix-build-out-link.md
Normal file
13
doc/manual/rl-next/nix-build-out-link.md
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
---
|
||||||
|
synopsis: Change `nix-build -o ""` to behave like `--no-out-link`
|
||||||
|
cls: [2103]
|
||||||
|
category: Fixes
|
||||||
|
credits: lilyball
|
||||||
|
---
|
||||||
|
|
||||||
|
[`nix-build`](@docroot@/command-ref/nix-build.md)now treats <code>[--out-link](@docroot@/command-ref/nix-build.md#opt-out-link) ''</code>
|
||||||
|
the same as [`--no-out-link`](@docroot@/command-ref/nix-build.md#opt-no-out-link). This matches
|
||||||
|
[`nix build`](@docroot@/command-ref/new-cli/nix3-build.md) behavior. Previously when building the default output it
|
||||||
|
would have resulted in throwing an error saying the current working directory already exists, and when building any
|
||||||
|
other output it would have resulted in a symlink starting with a hyphen such as `-doc`, which is a footgun for
|
||||||
|
terminal commands.
|
15
doc/manual/rl-next/temp-dir.md
Normal file
15
doc/manual/rl-next/temp-dir.md
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
---
|
||||||
|
synopsis: Add a `temp-dir` setting to set the temporary directory location
|
||||||
|
issues: [7731, 8995, fj#112, fj#253]
|
||||||
|
cls: [2103]
|
||||||
|
category: Improvements
|
||||||
|
credits: lilyball
|
||||||
|
---
|
||||||
|
|
||||||
|
[`temp-dir`](@docroot@/command-ref/conf-file.md#conf-temp-dir) can now be set in the Nix
|
||||||
|
configuration to change the temporary directory. This can be used to relocate all temporary files
|
||||||
|
to another filesystem without affecting the `TMPDIR` env var inherited by interactive
|
||||||
|
`nix-shell`/`nix shell` shells or `nix run` commands.
|
||||||
|
|
||||||
|
Also on macOS, the `TMPDIR` env var is no longer unset for interactive shells when pointing
|
||||||
|
to a per-session `/var/folders/` directory.
|
|
@ -25,6 +25,7 @@
|
||||||
#include "legacy.hh"
|
#include "legacy.hh"
|
||||||
#include "shlex.hh"
|
#include "shlex.hh"
|
||||||
#include "nix-build.hh"
|
#include "nix-build.hh"
|
||||||
|
#include "temporary-dir.hh"
|
||||||
|
|
||||||
extern char * * environ __attribute__((weak)); // Man what even is this
|
extern char * * environ __attribute__((weak)); // Man what even is this
|
||||||
|
|
||||||
|
@ -55,8 +56,6 @@ static void main_nix_build(int argc, char * * argv)
|
||||||
std::string script;
|
std::string script;
|
||||||
std::vector<std::string> savedArgs;
|
std::vector<std::string> savedArgs;
|
||||||
|
|
||||||
AutoDelete tmpDir(createTempDir("", myName));
|
|
||||||
|
|
||||||
std::string outLink = "./result";
|
std::string outLink = "./result";
|
||||||
|
|
||||||
// List of environment variables kept for --pure
|
// List of environment variables kept for --pure
|
||||||
|
@ -102,7 +101,6 @@ static void main_nix_build(int argc, char * * argv)
|
||||||
|
|
||||||
MyArgs myArgs(myName, [&](Strings::iterator & arg, const Strings::iterator & end) {
|
MyArgs myArgs(myName, [&](Strings::iterator & arg, const Strings::iterator & end) {
|
||||||
if (*arg == "--help") {
|
if (*arg == "--help") {
|
||||||
deletePath(tmpDir);
|
|
||||||
showManPage(myName);
|
showManPage(myName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,7 +111,7 @@ static void main_nix_build(int argc, char * * argv)
|
||||||
; // obsolete
|
; // obsolete
|
||||||
|
|
||||||
else if (*arg == "--no-out-link" || *arg == "--no-link")
|
else if (*arg == "--no-out-link" || *arg == "--no-link")
|
||||||
outLink = (Path) tmpDir + "/result";
|
outLink = "";
|
||||||
|
|
||||||
else if (*arg == "--attr" || *arg == "-A")
|
else if (*arg == "--attr" || *arg == "-A")
|
||||||
attrPaths.push_back(getArg(*arg, arg, end));
|
attrPaths.push_back(getArg(*arg, arg, end));
|
||||||
|
@ -198,6 +196,10 @@ static void main_nix_build(int argc, char * * argv)
|
||||||
if (packages && fromArgs)
|
if (packages && fromArgs)
|
||||||
throw UsageError("'-p' and '-E' are mutually exclusive");
|
throw UsageError("'-p' and '-E' are mutually exclusive");
|
||||||
|
|
||||||
|
AutoDelete tmpDir(createTempDir("", myName));
|
||||||
|
if (outLink.empty())
|
||||||
|
outLink = (Path) tmpDir + "/result";
|
||||||
|
|
||||||
auto store = openStore();
|
auto store = openStore();
|
||||||
auto evalStore = myArgs.evalStoreUrl ? openStore(*myArgs.evalStoreUrl) : store;
|
auto evalStore = myArgs.evalStoreUrl ? openStore(*myArgs.evalStoreUrl) : store;
|
||||||
|
|
||||||
|
@ -416,8 +418,6 @@ static void main_nix_build(int argc, char * * argv)
|
||||||
// Set the environment.
|
// Set the environment.
|
||||||
auto env = getEnv();
|
auto env = getEnv();
|
||||||
|
|
||||||
auto tmp = defaultTempDir();
|
|
||||||
|
|
||||||
if (pure) {
|
if (pure) {
|
||||||
decltype(env) newEnv;
|
decltype(env) newEnv;
|
||||||
for (auto & i : env)
|
for (auto & i : env)
|
||||||
|
@ -428,7 +428,8 @@ static void main_nix_build(int argc, char * * argv)
|
||||||
env["__ETC_PROFILE_SOURCED"] = "1";
|
env["__ETC_PROFILE_SOURCED"] = "1";
|
||||||
}
|
}
|
||||||
|
|
||||||
env["NIX_BUILD_TOP"] = env["TMPDIR"] = env["TEMPDIR"] = env["TMP"] = env["TEMP"] = tmp;
|
// Don't use defaultTempDir() here! We want to preserve the user's TMPDIR for the shell
|
||||||
|
env["NIX_BUILD_TOP"] = env["TMPDIR"] = env["TEMPDIR"] = env["TMP"] = env["TEMP"] = getEnvNonEmpty("TMPDIR").value_or("/tmp");
|
||||||
env["NIX_STORE"] = store->storeDir;
|
env["NIX_STORE"] = store->storeDir;
|
||||||
env["NIX_BUILD_CORES"] = std::to_string(settings.buildCores);
|
env["NIX_BUILD_CORES"] = std::to_string(settings.buildCores);
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "legacy.hh"
|
#include "legacy.hh"
|
||||||
#include "fetchers.hh"
|
#include "fetchers.hh"
|
||||||
#include "eval-settings.hh" // for defexpr
|
#include "eval-settings.hh" // for defexpr
|
||||||
|
#include "temporary-dir.hh"
|
||||||
#include "users.hh"
|
#include "users.hh"
|
||||||
#include "nix-channel.hh"
|
#include "nix-channel.hh"
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "logging.hh"
|
#include "logging.hh"
|
||||||
#include "names.hh"
|
#include "names.hh"
|
||||||
#include "store-api.hh"
|
#include "store-api.hh"
|
||||||
|
#include "temporary-dir.hh"
|
||||||
#include "url-name.hh"
|
#include "url-name.hh"
|
||||||
|
|
||||||
namespace nix
|
namespace nix
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "processes.hh"
|
#include "processes.hh"
|
||||||
#include "tarfile.hh"
|
#include "tarfile.hh"
|
||||||
#include "store-api.hh"
|
#include "store-api.hh"
|
||||||
|
#include "temporary-dir.hh"
|
||||||
#include "url-parts.hh"
|
#include "url-parts.hh"
|
||||||
#include "pathlocks.hh"
|
#include "pathlocks.hh"
|
||||||
#include "users.hh"
|
#include "users.hh"
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include "cache.hh"
|
#include "cache.hh"
|
||||||
#include "processes.hh"
|
#include "processes.hh"
|
||||||
#include "store-api.hh"
|
#include "store-api.hh"
|
||||||
|
#include "temporary-dir.hh"
|
||||||
#include "url-parts.hh"
|
#include "url-parts.hh"
|
||||||
#include "users.hh"
|
#include "users.hh"
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "store-api.hh"
|
#include "store-api.hh"
|
||||||
#include "archive.hh"
|
#include "archive.hh"
|
||||||
#include "tarfile.hh"
|
#include "tarfile.hh"
|
||||||
|
#include "temporary-dir.hh"
|
||||||
#include "types.hh"
|
#include "types.hh"
|
||||||
#include "split.hh"
|
#include "split.hh"
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "remote-fs-accessor.hh"
|
#include "remote-fs-accessor.hh"
|
||||||
#include "nar-info-disk-cache.hh" // IWYU pragma: keep
|
#include "nar-info-disk-cache.hh" // IWYU pragma: keep
|
||||||
#include "nar-accessor.hh"
|
#include "nar-accessor.hh"
|
||||||
|
#include "temporary-dir.hh"
|
||||||
#include "thread-pool.hh"
|
#include "thread-pool.hh"
|
||||||
#include "signals.hh"
|
#include "signals.hh"
|
||||||
#include "strings.hh"
|
#include "strings.hh"
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "indirect-root-store.hh"
|
#include "indirect-root-store.hh"
|
||||||
#include "machines.hh"
|
#include "machines.hh"
|
||||||
#include "store-api.hh"
|
#include "store-api.hh"
|
||||||
|
#include "temporary-dir.hh"
|
||||||
#include "worker.hh"
|
#include "worker.hh"
|
||||||
#include "builtins.hh"
|
#include "builtins.hh"
|
||||||
#include "builtins/buildenv.hh"
|
#include "builtins/buildenv.hh"
|
||||||
|
|
|
@ -468,11 +468,6 @@ void initLibStore() {
|
||||||
[1] https://github.com/apple-oss-distributions/objc4/blob/01edf1705fbc3ff78a423cd21e03dfc21eb4d780/runtime/objc-initialize.mm#L614-L636
|
[1] https://github.com/apple-oss-distributions/objc4/blob/01edf1705fbc3ff78a423cd21e03dfc21eb4d780/runtime/objc-initialize.mm#L614-L636
|
||||||
*/
|
*/
|
||||||
curl_global_init(CURL_GLOBAL_ALL);
|
curl_global_init(CURL_GLOBAL_ALL);
|
||||||
/* On macOS, don't use the per-session TMPDIR (as set e.g. by
|
|
||||||
sshd). This breaks build users because they don't have access
|
|
||||||
to the TMPDIR, in particular in ‘nix-store --serve’. */
|
|
||||||
if (defaultTempDir().starts_with("/var/folders/"))
|
|
||||||
unsetenv("TMPDIR");
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
registerStoreImplementations();
|
registerStoreImplementations();
|
||||||
|
|
|
@ -615,11 +615,11 @@ public:
|
||||||
)"};
|
)"};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Setting<std::optional<Path>> buildDir{this, std::nullopt, "build-dir",
|
PathsSetting<std::optional<Path>> buildDir{this, std::nullopt, "build-dir",
|
||||||
R"(
|
R"(
|
||||||
The directory on the host, in which derivations' temporary build directories are created.
|
The directory on the host, in which derivations' temporary build directories are created.
|
||||||
|
|
||||||
If not set, Nix will use the system temporary directory indicated by the `TMPDIR` environment variable.
|
If not set, Nix will use the [`temp-dir`](#conf-temp-dir) setting if set, otherwise the system temporary directory indicated by the `TMPDIR` environment variable.
|
||||||
Note that builds are often performed by the Nix daemon, so its `TMPDIR` is used, and not that of the Nix command line interface.
|
Note that builds are often performed by the Nix daemon, so its `TMPDIR` is used, and not that of the Nix command line interface.
|
||||||
|
|
||||||
This is also the location where [`--keep-failed`](@docroot@/command-ref/opt-common.md#opt-keep-failed) leaves its files.
|
This is also the location where [`--keep-failed`](@docroot@/command-ref/opt-common.md#opt-keep-failed) leaves its files.
|
||||||
|
@ -627,6 +627,18 @@ public:
|
||||||
If Nix runs without sandbox, or if the platform does not support sandboxing with bind mounts (e.g. macOS), then the [`builder`](@docroot@/language/derivations.md#attr-builder)'s environment will contain this directory, instead of the virtual location [`sandbox-build-dir`](#conf-sandbox-build-dir).
|
If Nix runs without sandbox, or if the platform does not support sandboxing with bind mounts (e.g. macOS), then the [`builder`](@docroot@/language/derivations.md#attr-builder)'s environment will contain this directory, instead of the virtual location [`sandbox-build-dir`](#conf-sandbox-build-dir).
|
||||||
)"};
|
)"};
|
||||||
|
|
||||||
|
PathsSetting<std::optional<Path>> tempDir{this, std::nullopt, "temp-dir",
|
||||||
|
R"(
|
||||||
|
The directory on the host used as the default temporary directory.
|
||||||
|
|
||||||
|
If not set, Nix will use the system temporary directory indicated by the `TMPDIR` environment variable.
|
||||||
|
|
||||||
|
This will be used for anything that would otherwise fall back to `TMPDIR`, and the inherited `TMPDIR` value will be preserved for child processes to use.
|
||||||
|
If [`build-dir`](#conf-build-dir) is set, that takes precedence over this where it applies.
|
||||||
|
|
||||||
|
If set, the value must be a path that exists and is accessible to all users.
|
||||||
|
)"};
|
||||||
|
|
||||||
Setting<PathSet> allowedImpureHostPrefixes{this, {}, "allowed-impure-host-deps",
|
Setting<PathSet> allowedImpureHostPrefixes{this, {}, "allowed-impure-host-deps",
|
||||||
"Which prefixes to allow derivations to ask for access to (primarily for Darwin)."};
|
"Which prefixes to allow derivations to ask for access to (primarily for Darwin)."};
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include "globals.hh"
|
#include "globals.hh"
|
||||||
#include "archive.hh"
|
#include "archive.hh"
|
||||||
#include "pathlocks.hh"
|
#include "pathlocks.hh"
|
||||||
|
#include "temporary-dir.hh"
|
||||||
#include "worker-protocol.hh"
|
#include "worker-protocol.hh"
|
||||||
#include "derivations.hh"
|
#include "derivations.hh"
|
||||||
#include "nar-info.hh"
|
#include "nar-info.hh"
|
||||||
|
|
|
@ -77,6 +77,7 @@ libstore_sources = files(
|
||||||
'ssh-store.cc',
|
'ssh-store.cc',
|
||||||
'ssh.cc',
|
'ssh.cc',
|
||||||
'store-api.cc',
|
'store-api.cc',
|
||||||
|
'temporary-dir.cc',
|
||||||
'uds-remote-store.cc',
|
'uds-remote-store.cc',
|
||||||
'worker-protocol.cc',
|
'worker-protocol.cc',
|
||||||
'build/child.cc',
|
'build/child.cc',
|
||||||
|
@ -160,6 +161,7 @@ libstore_headers = files(
|
||||||
'ssh-store.hh',
|
'ssh-store.hh',
|
||||||
'store-api.hh',
|
'store-api.hh',
|
||||||
'store-cast.hh',
|
'store-cast.hh',
|
||||||
|
'temporary-dir.hh',
|
||||||
'uds-remote-store.hh',
|
'uds-remote-store.hh',
|
||||||
'worker-protocol-impl.hh',
|
'worker-protocol-impl.hh',
|
||||||
'worker-protocol.hh',
|
'worker-protocol.hh',
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "finally.hh"
|
#include "finally.hh"
|
||||||
#include "logging.hh"
|
#include "logging.hh"
|
||||||
#include "strings.hh"
|
#include "strings.hh"
|
||||||
|
#include "temporary-dir.hh"
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
|
|
42
src/libstore/temporary-dir.cc
Normal file
42
src/libstore/temporary-dir.cc
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
#include "temporary-dir.hh"
|
||||||
|
|
||||||
|
#include "file-system.hh"
|
||||||
|
#include "globals.hh"
|
||||||
|
|
||||||
|
namespace nix {
|
||||||
|
|
||||||
|
Path createTempDir(const Path & tmpRoot, const Path & prefix,
|
||||||
|
bool includePid, bool useGlobalCounter, mode_t mode)
|
||||||
|
{
|
||||||
|
return createTempSubdir(tmpRoot.empty() ? defaultTempDir() : tmpRoot, prefix, includePid, useGlobalCounter, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<AutoCloseFD, Path> createTempFile(const Path & prefix)
|
||||||
|
{
|
||||||
|
Path tmpl(defaultTempDir() + "/" + prefix + ".XXXXXX");
|
||||||
|
// FIXME: use O_TMPFILE.
|
||||||
|
AutoCloseFD fd(mkstemp(tmpl.data()));
|
||||||
|
if (!fd)
|
||||||
|
throw SysError("creating temporary file '%s'", tmpl);
|
||||||
|
closeOnExec(fd.get());
|
||||||
|
return {std::move(fd), tmpl};
|
||||||
|
}
|
||||||
|
|
||||||
|
Path defaultTempDir()
|
||||||
|
{
|
||||||
|
return settings.tempDir.get().or_else([] {
|
||||||
|
return getEnvNonEmpty("TMPDIR").and_then([](auto val) -> std::optional<Path> {
|
||||||
|
#if __APPLE__
|
||||||
|
/* On macOS, don't use the per-session TMPDIR (as set e.g. by
|
||||||
|
sshd). This breaks build users because they don't have access
|
||||||
|
to the TMPDIR, in particular in ‘nix-store --serve’. */
|
||||||
|
if (val.starts_with("/var/folders/")) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return val;
|
||||||
|
});
|
||||||
|
}).value_or("/tmp");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
24
src/libstore/temporary-dir.hh
Normal file
24
src/libstore/temporary-dir.hh
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
#pragma once
|
||||||
|
///@file
|
||||||
|
|
||||||
|
#include "file-system.hh"
|
||||||
|
|
||||||
|
namespace nix {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a temporary directory.
|
||||||
|
*/
|
||||||
|
Path createTempDir(const Path & tmpRoot = "", const Path & prefix = "nix",
|
||||||
|
bool includePid = true, bool useGlobalCounter = true, mode_t mode = 0755);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a temporary file, returning a file handle and its path.
|
||||||
|
*/
|
||||||
|
std::pair<AutoCloseFD, Path> createTempFile(const Path & prefix = "nix");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return settings.tempDir, `TMPDIR`, or the default temporary directory if unset or empty.
|
||||||
|
*/
|
||||||
|
Path defaultTempDir();
|
||||||
|
|
||||||
|
}
|
|
@ -562,21 +562,17 @@ void AutoDelete::reset(const Path & p, bool recursive) {
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
std::string defaultTempDir() {
|
static Path tempName(PathView parent, const Path & prefix, bool includePid,
|
||||||
return getEnvNonEmpty("TMPDIR").value_or("/tmp");
|
|
||||||
}
|
|
||||||
|
|
||||||
static Path tempName(Path tmpRoot, const Path & prefix, bool includePid,
|
|
||||||
std::atomic<unsigned int> & counter)
|
std::atomic<unsigned int> & counter)
|
||||||
{
|
{
|
||||||
tmpRoot = canonPath(tmpRoot.empty() ? defaultTempDir() : tmpRoot, true);
|
auto tmpRoot = canonPath(parent, true);
|
||||||
if (includePid)
|
if (includePid)
|
||||||
return fmt("%1%/%2%-%3%-%4%", tmpRoot, prefix, getpid(), counter++);
|
return fmt("%1%/%2%-%3%-%4%", tmpRoot, prefix, getpid(), counter++);
|
||||||
else
|
else
|
||||||
return fmt("%1%/%2%-%3%", tmpRoot, prefix, counter++);
|
return fmt("%1%/%2%-%3%", tmpRoot, prefix, counter++);
|
||||||
}
|
}
|
||||||
|
|
||||||
Path createTempDir(const Path & tmpRoot, const Path & prefix,
|
Path createTempSubdir(const Path & parent, const Path & prefix,
|
||||||
bool includePid, bool useGlobalCounter, mode_t mode)
|
bool includePid, bool useGlobalCounter, mode_t mode)
|
||||||
{
|
{
|
||||||
static std::atomic<unsigned int> globalCounter = 0;
|
static std::atomic<unsigned int> globalCounter = 0;
|
||||||
|
@ -585,7 +581,7 @@ Path createTempDir(const Path & tmpRoot, const Path & prefix,
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
checkInterrupt();
|
checkInterrupt();
|
||||||
Path tmpDir = tempName(tmpRoot, prefix, includePid, counter);
|
Path tmpDir = tempName(parent, prefix, includePid, counter);
|
||||||
if (mkdir(tmpDir.c_str(), mode) == 0) {
|
if (mkdir(tmpDir.c_str(), mode) == 0) {
|
||||||
#if __FreeBSD__
|
#if __FreeBSD__
|
||||||
/* Explicitly set the group of the directory. This is to
|
/* Explicitly set the group of the directory. This is to
|
||||||
|
@ -606,18 +602,6 @@ Path createTempDir(const Path & tmpRoot, const Path & prefix,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::pair<AutoCloseFD, Path> createTempFile(const Path & prefix)
|
|
||||||
{
|
|
||||||
Path tmpl(defaultTempDir() + "/" + prefix + ".XXXXXX");
|
|
||||||
// FIXME: use O_TMPFILE.
|
|
||||||
AutoCloseFD fd(mkstemp(tmpl.data()));
|
|
||||||
if (!fd)
|
|
||||||
throw SysError("creating temporary file '%s'", tmpl);
|
|
||||||
closeOnExec(fd.get());
|
|
||||||
return {std::move(fd), tmpl};
|
|
||||||
}
|
|
||||||
|
|
||||||
Path makeTempPath(const Path & root, const Path & suffix)
|
Path makeTempPath(const Path & root, const Path & suffix)
|
||||||
{
|
{
|
||||||
// start the counter at a random value to minimize issues with preexisting temp paths
|
// start the counter at a random value to minimize issues with preexisting temp paths
|
||||||
|
@ -721,7 +705,7 @@ void moveFile(const Path & oldName, const Path & newName)
|
||||||
auto newPath = fs::path(newName);
|
auto newPath = fs::path(newName);
|
||||||
// For the move to be as atomic as possible, copy to a temporary
|
// For the move to be as atomic as possible, copy to a temporary
|
||||||
// directory
|
// directory
|
||||||
fs::path temp = createTempDir(newPath.parent_path(), "rename-tmp");
|
fs::path temp = createTempSubdir(newPath.parent_path(), "rename-tmp");
|
||||||
Finally removeTemp = [&]() { fs::remove(temp); };
|
Finally removeTemp = [&]() { fs::remove(temp); };
|
||||||
auto tempCopyTarget = temp / "copy-target";
|
auto tempCopyTarget = temp / "copy-target";
|
||||||
if (e.code().value() == EXDEV) {
|
if (e.code().value() == EXDEV) {
|
||||||
|
|
|
@ -288,21 +288,11 @@ struct DIRDeleter
|
||||||
typedef std::unique_ptr<DIR, DIRDeleter> AutoCloseDir;
|
typedef std::unique_ptr<DIR, DIRDeleter> AutoCloseDir;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a temporary directory.
|
* Create a temporary directory in a given parent directory.
|
||||||
*/
|
*/
|
||||||
Path createTempDir(const Path & tmpRoot = "", const Path & prefix = "nix",
|
Path createTempSubdir(const Path & parent, const Path & prefix = "nix",
|
||||||
bool includePid = true, bool useGlobalCounter = true, mode_t mode = 0755);
|
bool includePid = true, bool useGlobalCounter = true, mode_t mode = 0755);
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a temporary file, returning a file handle and its path.
|
|
||||||
*/
|
|
||||||
std::pair<AutoCloseFD, Path> createTempFile(const Path & prefix = "nix");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return `TMPDIR`, or the default temporary directory if unset or empty.
|
|
||||||
*/
|
|
||||||
Path defaultTempDir();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return temporary path constructed by appending a suffix to a root path.
|
* Return temporary path constructed by appending a suffix to a root path.
|
||||||
*
|
*
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "outputs-spec.hh"
|
#include "outputs-spec.hh"
|
||||||
#include "derivations.hh"
|
#include "derivations.hh"
|
||||||
#include "run.hh"
|
#include "run.hh"
|
||||||
|
#include "temporary-dir.hh"
|
||||||
|
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "attr-path.hh"
|
#include "attr-path.hh"
|
||||||
#include "eval-inline.hh" // IWYU pragma: keep
|
#include "eval-inline.hh" // IWYU pragma: keep
|
||||||
#include "legacy.hh"
|
#include "legacy.hh"
|
||||||
|
#include "temporary-dir.hh"
|
||||||
#include "terminal.hh"
|
#include "terminal.hh"
|
||||||
#include "prefetch-command.hh"
|
#include "prefetch-command.hh"
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "current-process.hh"
|
#include "current-process.hh"
|
||||||
|
|
||||||
#if __linux__
|
#if __linux__
|
||||||
|
#include "temporary-dir.hh"
|
||||||
#include <sys/mount.h>
|
#include <sys/mount.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -49,6 +49,50 @@ test_custom_build_dir() {
|
||||||
}
|
}
|
||||||
test_custom_build_dir
|
test_custom_build_dir
|
||||||
|
|
||||||
|
test_custom_temp_dir() {
|
||||||
|
# like test_custom_build_dir(), but uses the temp-dir setting instead
|
||||||
|
# build-dir inherits from temp-dir when build-dir is unset
|
||||||
|
local customTempDir="$TEST_ROOT/custom-temp-dir"
|
||||||
|
|
||||||
|
mkdir "$customTempDir"
|
||||||
|
nix-build check.nix -A failed --argstr checkBuildId $checkBuildId \
|
||||||
|
--no-out-link --keep-failed --option temp-dir "$customTempDir" 2> $TEST_ROOT/log || status=$?
|
||||||
|
[ "$status" = "100" ]
|
||||||
|
[[ 1 == "$(count "$customTempDir/nix-build-"*)" ]]
|
||||||
|
local buildDir="$customTempDir/nix-build-"*
|
||||||
|
grep $checkBuildId $buildDir/checkBuildId
|
||||||
|
|
||||||
|
# also check a separate code path that doesn't involve build-dir
|
||||||
|
# nix-shell uses temp-dir for its rcfile path
|
||||||
|
rcpath=$(NIX_BUILD_SHELL=$SHELL nix-shell check.nix -A deterministic --option temp-dir "$customTempDir" --run 'echo $0' 2> $TEST_ROOT/log)
|
||||||
|
# rcpath is <temp-dir>/nix-shell-*/rc
|
||||||
|
[[ $rcpath = "$customTempDir"/* ]]
|
||||||
|
}
|
||||||
|
test_custom_temp_dir
|
||||||
|
|
||||||
|
test_shell_preserves_tmpdir() {
|
||||||
|
# ensure commands that spawn interactive shells don't overwrite TMPDIR with temp-dir
|
||||||
|
local envTempDir=$TEST_ROOT/shell-temp-dir-env
|
||||||
|
mkdir $envTempDir
|
||||||
|
local settingTempDir=$TEST_ROOT/shell-temp-dir-setting
|
||||||
|
mkdir $settingTempDir
|
||||||
|
|
||||||
|
# FIXME: switch to check.nix's deterministic once `nix develop` doesn't need `outputs`
|
||||||
|
# https://git.lix.systems/lix-project/lix/issues/556
|
||||||
|
local expr='with import ./config.nix; mkDerivation { name = "foo"; buildCommand = "echo foo > $out"; outputs = [ "out" ]; }'
|
||||||
|
|
||||||
|
local output
|
||||||
|
output=$(TMPDIR=$envTempDir NIX_BUILD_SHELL=$SHELL nix-shell -E "$expr" --option temp-dir "$settingTempDir" --command 'echo $TMPDIR' 2> $TEST_ROOT/log)
|
||||||
|
[[ $output = "$envTempDir" ]]
|
||||||
|
|
||||||
|
output=$(TMPDIR=$envTempDir nix develop --impure -E "$expr" --option temp-dir "$settingTempDir" --command bash -c 'echo $TMPDIR' 2> $TEST_ROOT/log)
|
||||||
|
[[ $output = "$envTempDir"/nix-shell.* ]]
|
||||||
|
|
||||||
|
output=$(TMPDIR=$envTempDir nix shell --impure -E "$expr" --option temp-dir "$settingTempDir" --command bash -c 'echo $TMPDIR' 2> $TEST_ROOT/log)
|
||||||
|
[[ $output = "$envTempDir" ]]
|
||||||
|
}
|
||||||
|
test_shell_preserves_tmpdir
|
||||||
|
|
||||||
nix-build check.nix -A deterministic --argstr checkBuildId $checkBuildId \
|
nix-build check.nix -A deterministic --argstr checkBuildId $checkBuildId \
|
||||||
--no-out-link 2> $TEST_ROOT/log
|
--no-out-link 2> $TEST_ROOT/log
|
||||||
checkBuildTempDirRemoved $TEST_ROOT/log
|
checkBuildTempDirRemoved $TEST_ROOT/log
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
#include <rapidcheck/gtest.h>
|
#include <rapidcheck/gtest.h>
|
||||||
#include "sqlite.hh"
|
#include "sqlite.hh"
|
||||||
|
#include "temporary-dir.hh"
|
||||||
#include <sqlite3.h>
|
#include <sqlite3.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue