mirror of
https://github.com/NixOS/nix
synced 2025-07-06 21:41:48 +02:00
Merge remote-tracking branch 'origin/2.24-maintenance' into sync-2.24.9
This commit is contained in:
commit
828f8e197e
24 changed files with 246 additions and 96 deletions
|
@ -159,6 +159,27 @@ static Object peelToTreeOrBlob(git_object * obj)
|
|||
return peelObject<Object>(obj, GIT_OBJECT_TREE);
|
||||
}
|
||||
|
||||
static void initRepoAtomically(std::filesystem::path &path, bool bare) {
|
||||
if (pathExists(path.string())) return;
|
||||
|
||||
Path tmpDir = createTempDir(std::filesystem::path(path).parent_path());
|
||||
AutoDelete delTmpDir(tmpDir, true);
|
||||
Repository tmpRepo;
|
||||
|
||||
if (git_repository_init(Setter(tmpRepo), tmpDir.c_str(), bare))
|
||||
throw Error("creating Git repository %s: %s", path, git_error_last()->message);
|
||||
try {
|
||||
std::filesystem::rename(tmpDir, path);
|
||||
} catch (std::filesystem::filesystem_error & e) {
|
||||
if (e.code() == std::errc::file_exists) // Someone might race us to create the repository.
|
||||
return;
|
||||
else
|
||||
throw SysError("moving temporary git repository from %s to %s", tmpDir, path);
|
||||
}
|
||||
// we successfully moved the repository, so the temporary directory no longer exists.
|
||||
delTmpDir.cancel();
|
||||
}
|
||||
|
||||
struct GitRepoImpl : GitRepo, std::enable_shared_from_this<GitRepoImpl>
|
||||
{
|
||||
/** Location of the repository on disk. */
|
||||
|
@ -170,13 +191,10 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this<GitRepoImpl>
|
|||
{
|
||||
initLibGit2();
|
||||
|
||||
if (pathExists(path.string())) {
|
||||
if (git_repository_open(Setter(repo), path.string().c_str()))
|
||||
throw Error("opening Git repository '%s': %s", path, git_error_last()->message);
|
||||
} else {
|
||||
if (git_repository_init(Setter(repo), path.string().c_str(), bare))
|
||||
throw Error("creating Git repository '%s': %s", path, git_error_last()->message);
|
||||
}
|
||||
initRepoAtomically(path, bare);
|
||||
if (git_repository_open(Setter(repo), path.string().c_str()))
|
||||
throw Error("opening Git repository '%s': %s", path, git_error_last()->message);
|
||||
|
||||
}
|
||||
|
||||
operator git_repository * ()
|
||||
|
@ -837,8 +855,24 @@ struct GitFileSystemObjectSinkImpl : GitFileSystemObjectSink
|
|||
|
||||
void pushBuilder(std::string name)
|
||||
{
|
||||
const git_tree_entry * entry;
|
||||
Tree prevTree = nullptr;
|
||||
|
||||
if (!pendingDirs.empty() &&
|
||||
(entry = git_treebuilder_get(pendingDirs.back().builder.get(), name.c_str())))
|
||||
{
|
||||
/* Clone a tree that we've already finished. This happens
|
||||
if a tarball has directory entries that are not
|
||||
contiguous. */
|
||||
if (git_tree_entry_type(entry) != GIT_OBJECT_TREE)
|
||||
throw Error("parent of '%s' is not a directory", name);
|
||||
|
||||
if (git_tree_entry_to_object((git_object * *) (git_tree * *) Setter(prevTree), *repo, entry))
|
||||
throw Error("looking up parent of '%s': %s", name, git_error_last()->message);
|
||||
}
|
||||
|
||||
git_treebuilder * b;
|
||||
if (git_treebuilder_new(&b, *repo, nullptr))
|
||||
if (git_treebuilder_new(&b, *repo, prevTree.get()))
|
||||
throw Error("creating a tree builder: %s", git_error_last()->message);
|
||||
pendingDirs.push_back({ .name = std::move(name), .builder = TreeBuilder(b) });
|
||||
};
|
||||
|
|
|
@ -90,6 +90,7 @@ DownloadFileResult downloadFile(
|
|||
/* Cache metadata for all URLs in the redirect chain. */
|
||||
for (auto & url : res.urls) {
|
||||
key.second.insert_or_assign("url", url);
|
||||
assert(!res.urls.empty());
|
||||
infoAttrs.insert_or_assign("url", *res.urls.rbegin());
|
||||
getCache()->upsert(key, *store, infoAttrs, *storePath);
|
||||
}
|
||||
|
|
|
@ -9,7 +9,8 @@ namespace nix {
|
|||
void builtinFetchurl(
|
||||
const BasicDerivation & drv,
|
||||
const std::map<std::string, Path> & outputs,
|
||||
const std::string & netrcData);
|
||||
const std::string & netrcData,
|
||||
const std::string & caFileData);
|
||||
|
||||
void builtinUnpackChannel(
|
||||
const BasicDerivation & drv,
|
||||
|
|
|
@ -9,7 +9,8 @@ namespace nix {
|
|||
void builtinFetchurl(
|
||||
const BasicDerivation & drv,
|
||||
const std::map<std::string, Path> & outputs,
|
||||
const std::string & netrcData)
|
||||
const std::string & netrcData,
|
||||
const std::string & caFileData)
|
||||
{
|
||||
/* Make the host's netrc data available. Too bad curl requires
|
||||
this to be stored in a file. It would be nice if we could just
|
||||
|
@ -19,6 +20,9 @@ void builtinFetchurl(
|
|||
writeFile(settings.netrcFile, netrcData, 0600);
|
||||
}
|
||||
|
||||
settings.caFile = "ca-certificates.crt";
|
||||
writeFile(settings.caFile, caFileData, 0600);
|
||||
|
||||
auto out = get(drv.outputs, "out");
|
||||
if (!out)
|
||||
throw Error("'builtin:fetchurl' requires an 'out' output");
|
||||
|
|
|
@ -754,12 +754,17 @@ struct curlFileTransfer : public FileTransfer
|
|||
|
||||
S3Helper s3Helper(profile, region, scheme, endpoint);
|
||||
|
||||
Activity act(*logger, lvlTalkative, actFileTransfer,
|
||||
fmt("downloading '%s'", request.uri),
|
||||
{request.uri}, request.parentAct);
|
||||
|
||||
// FIXME: implement ETag
|
||||
auto s3Res = s3Helper.getObject(bucketName, key);
|
||||
FileTransferResult res;
|
||||
if (!s3Res.data)
|
||||
throw FileTransferError(NotFound, "S3 object '%s' does not exist", request.uri);
|
||||
res.data = std::move(*s3Res.data);
|
||||
res.urls.push_back(request.uri);
|
||||
callback(std::move(res));
|
||||
#else
|
||||
throw nix::Error("cannot download '%s' because Nix is not built with S3 support", request.uri);
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "globals.hh"
|
||||
#include "compression.hh"
|
||||
#include "filetransfer.hh"
|
||||
#include "signals.hh"
|
||||
|
||||
#include <aws/core/Aws.h>
|
||||
#include <aws/core/VersionConfig.h>
|
||||
|
@ -117,6 +118,7 @@ class RetryStrategy : public Aws::Client::DefaultRetryStrategy
|
|||
{
|
||||
bool ShouldRetry(const Aws::Client::AWSError<Aws::Client::CoreErrors>& error, long attemptedRetries) const override
|
||||
{
|
||||
checkInterrupt();
|
||||
auto retry = Aws::Client::DefaultRetryStrategy::ShouldRetry(error, attemptedRetries);
|
||||
if (retry)
|
||||
printError("AWS error '%s' (%s), will retry in %d ms",
|
||||
|
|
|
@ -1746,13 +1746,20 @@ void LocalDerivationGoal::runChild()
|
|||
|
||||
bool setUser = true;
|
||||
|
||||
/* Make the contents of netrc available to builtin:fetchurl
|
||||
(which may run under a different uid and/or in a sandbox). */
|
||||
/* Make the contents of netrc and the CA certificate bundle
|
||||
available to builtin:fetchurl (which may run under a
|
||||
different uid and/or in a sandbox). */
|
||||
std::string netrcData;
|
||||
try {
|
||||
if (drv->isBuiltin() && drv->builder == "builtin:fetchurl")
|
||||
netrcData = readFile(settings.netrcFile);
|
||||
} catch (SystemError &) { }
|
||||
std::string caFileData;
|
||||
if (drv->isBuiltin() && drv->builder == "builtin:fetchurl") {
|
||||
try {
|
||||
netrcData = readFile(settings.netrcFile);
|
||||
} catch (SystemError &) { }
|
||||
|
||||
try {
|
||||
caFileData = readFile(settings.caFile);
|
||||
} catch (SystemError &) { }
|
||||
}
|
||||
|
||||
#if __linux__
|
||||
if (useChroot) {
|
||||
|
@ -2191,7 +2198,7 @@ void LocalDerivationGoal::runChild()
|
|||
worker.store.printStorePath(scratchOutputs.at(e.first)));
|
||||
|
||||
if (drv->builder == "builtin:fetchurl")
|
||||
builtinFetchurl(*drv, outputs, netrcData);
|
||||
builtinFetchurl(*drv, outputs, netrcData, caFileData);
|
||||
else if (drv->builder == "builtin:buildenv")
|
||||
builtinBuildenv(*drv, outputs);
|
||||
else if (drv->builder == "builtin:unpack-channel")
|
||||
|
|
|
@ -574,7 +574,28 @@ void setWriteTime(
|
|||
time_t modificationTime,
|
||||
std::optional<bool> optIsSymlink)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
#ifdef _WIN32
|
||||
// FIXME use `fs::last_write_time`.
|
||||
//
|
||||
// Would be nice to use std::filesystem unconditionally, but
|
||||
// doesn't support access time just modification time.
|
||||
//
|
||||
// System clock vs File clock issues also make that annoying.
|
||||
warn("Changing file times is not yet implemented on Windows, path is '%s'", path);
|
||||
#elif HAVE_UTIMENSAT && HAVE_DECL_AT_SYMLINK_NOFOLLOW
|
||||
struct timespec times[2] = {
|
||||
{
|
||||
.tv_sec = accessedTime,
|
||||
.tv_nsec = 0,
|
||||
},
|
||||
{
|
||||
.tv_sec = modificationTime,
|
||||
.tv_nsec = 0,
|
||||
},
|
||||
};
|
||||
if (utimensat(AT_FDCWD, path.c_str(), times, AT_SYMLINK_NOFOLLOW) == -1)
|
||||
throw SysError("changing modification time of '%s' (using `utimensat`)", path);
|
||||
#else
|
||||
struct timeval times[2] = {
|
||||
{
|
||||
.tv_sec = accessedTime,
|
||||
|
@ -585,42 +606,21 @@ void setWriteTime(
|
|||
.tv_usec = 0,
|
||||
},
|
||||
};
|
||||
#endif
|
||||
|
||||
auto nonSymlink = [&]{
|
||||
bool isSymlink = optIsSymlink
|
||||
? *optIsSymlink
|
||||
: fs::is_symlink(path);
|
||||
|
||||
if (!isSymlink) {
|
||||
#ifdef _WIN32
|
||||
// FIXME use `fs::last_write_time`.
|
||||
//
|
||||
// Would be nice to use std::filesystem unconditionally, but
|
||||
// doesn't support access time just modification time.
|
||||
//
|
||||
// System clock vs File clock issues also make that annoying.
|
||||
warn("Changing file times is not yet implemented on Windows, path is '%s'", path);
|
||||
#else
|
||||
if (utimes(path.c_str(), times) == -1) {
|
||||
|
||||
throw SysError("changing modification time of '%s' (not a symlink)", path);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
throw Error("Cannot modification time of symlink '%s'", path);
|
||||
}
|
||||
};
|
||||
|
||||
#if HAVE_LUTIMES
|
||||
if (lutimes(path.c_str(), times) == -1) {
|
||||
if (errno == ENOSYS)
|
||||
nonSymlink();
|
||||
else
|
||||
throw SysError("changing modification time of '%s'", path);
|
||||
}
|
||||
if (lutimes(path.c_str(), times) == -1)
|
||||
throw SysError("changing modification time of '%s'", path);
|
||||
#else
|
||||
nonSymlink();
|
||||
bool isSymlink = optIsSymlink
|
||||
? *optIsSymlink
|
||||
: fs::is_symlink(path);
|
||||
|
||||
if (!isSymlink) {
|
||||
if (utimes(path.c_str(), times) == -1)
|
||||
throw SysError("changing modification time of '%s' (not a symlink)", path);
|
||||
} else {
|
||||
throw Error("Cannot modification time of symlink '%s'", path);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -41,6 +41,8 @@ check_funcs = [
|
|||
# Optionally used to try to close more file descriptors (e.g. before
|
||||
# forking) on Unix.
|
||||
'sysconf',
|
||||
# Optionally used for changing the mtime of files and symlinks.
|
||||
'utimensat',
|
||||
]
|
||||
foreach funcspec : check_funcs
|
||||
define_name = 'HAVE_' + funcspec.underscorify().to_upper()
|
||||
|
@ -48,6 +50,8 @@ foreach funcspec : check_funcs
|
|||
configdata.set(define_name, define_value)
|
||||
endforeach
|
||||
|
||||
configdata.set('HAVE_DECL_AT_SYMLINK_NOFOLLOW', cxx.has_header_symbol('fcntl.h', 'AT_SYMLINK_NOFOLLOW').to_int())
|
||||
|
||||
subdir('build-utils-meson/threads')
|
||||
|
||||
if host_machine.system() == 'windows'
|
||||
|
|
|
@ -526,8 +526,6 @@ static void main_nix_build(int argc, char * * argv)
|
|||
// Set the environment.
|
||||
auto env = getEnv();
|
||||
|
||||
auto tmp = getEnvNonEmpty("TMPDIR").value_or("/tmp");
|
||||
|
||||
if (pure) {
|
||||
decltype(env) newEnv;
|
||||
for (auto & i : env)
|
||||
|
@ -538,18 +536,16 @@ static void main_nix_build(int argc, char * * argv)
|
|||
env["__ETC_PROFILE_SOURCED"] = "1";
|
||||
}
|
||||
|
||||
env["NIX_BUILD_TOP"] = env["TMPDIR"] = env["TEMPDIR"] = env["TMP"] = env["TEMP"] = tmp;
|
||||
env["NIX_BUILD_TOP"] = env["TMPDIR"] = env["TEMPDIR"] = env["TMP"] = env["TEMP"] = tmpDir.path();
|
||||
env["NIX_STORE"] = store->storeDir;
|
||||
env["NIX_BUILD_CORES"] = std::to_string(settings.buildCores);
|
||||
|
||||
auto passAsFile = tokenizeString<StringSet>(getOr(drv.env, "passAsFile", ""));
|
||||
|
||||
bool keepTmp = false;
|
||||
int fileNr = 0;
|
||||
|
||||
for (auto & var : drv.env)
|
||||
if (passAsFile.count(var.first)) {
|
||||
keepTmp = true;
|
||||
auto fn = ".attr-" + std::to_string(fileNr++);
|
||||
Path p = (tmpDir.path() / fn).string();
|
||||
writeFile(p, var.second);
|
||||
|
@ -591,7 +587,6 @@ static void main_nix_build(int argc, char * * argv)
|
|||
|
||||
env["NIX_ATTRS_SH_FILE"] = attrsSH;
|
||||
env["NIX_ATTRS_JSON_FILE"] = attrsJSON;
|
||||
keepTmp = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -601,12 +596,10 @@ static void main_nix_build(int argc, char * * argv)
|
|||
lose the current $PATH directories. */
|
||||
auto rcfile = (tmpDir.path() / "rc").string();
|
||||
std::string rc = fmt(
|
||||
R"(_nix_shell_clean_tmpdir() { command rm -rf %1%; }; )"s +
|
||||
(keepTmp ?
|
||||
"trap _nix_shell_clean_tmpdir EXIT; "
|
||||
"exitHooks+=(_nix_shell_clean_tmpdir); "
|
||||
"failureHooks+=(_nix_shell_clean_tmpdir); ":
|
||||
"_nix_shell_clean_tmpdir; ") +
|
||||
(R"(_nix_shell_clean_tmpdir() { command rm -rf %1%; };)"s
|
||||
"trap _nix_shell_clean_tmpdir EXIT; "
|
||||
"exitHooks+=(_nix_shell_clean_tmpdir); "
|
||||
"failureHooks+=(_nix_shell_clean_tmpdir); ") +
|
||||
(pure ? "" : "[ -n \"$PS1\" ] && [ -e ~/.bashrc ] && source ~/.bashrc;") +
|
||||
"%2%"
|
||||
// always clear PATH.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue