aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/manual/rclone.conf8
-rw-r--r--doc/manual/rl-next/repl-interrupt.md8
-rwxr-xr-xmaintainers/upload_manual.sh40
-rw-r--r--src/libcmd/repl.cc4
-rw-r--r--src/libmain/shared.cc11
-rw-r--r--src/libstore/build/local-derivation-goal.cc5
-rw-r--r--src/libstore/filetransfer.cc4
-rw-r--r--src/libutil/signals.cc9
-rw-r--r--src/libutil/signals.hh2
-rw-r--r--tests/functional/common/vars-and-functions.sh.in2
-rw-r--r--tests/functional/extra-sandbox-profile.nix19
-rw-r--r--tests/functional/extra-sandbox-profile.sh23
-rw-r--r--tests/functional/meson.build8
-rw-r--r--tests/functional/plugins.sh4
-rw-r--r--tests/unit/libstore/filetransfer.cc16
15 files changed, 131 insertions, 32 deletions
diff --git a/doc/manual/rclone.conf b/doc/manual/rclone.conf
new file mode 100644
index 000000000..c37c12638
--- /dev/null
+++ b/doc/manual/rclone.conf
@@ -0,0 +1,8 @@
+[lix-docs]
+type = s3
+provider = Other
+env_auth = true
+endpoint = https://s3.lix.systems
+location_constraint = garage
+region = garage
+acl = private
diff --git a/doc/manual/rl-next/repl-interrupt.md b/doc/manual/rl-next/repl-interrupt.md
new file mode 100644
index 000000000..61a8ab71e
--- /dev/null
+++ b/doc/manual/rl-next/repl-interrupt.md
@@ -0,0 +1,8 @@
+---
+synopsis: Interrupting builds in the REPL works more than once
+cls: 1097
+---
+
+Builds in the REPL can be interrupted by pressing Ctrl+C.
+Previously, this only worked once per REPL session; further attempts would be ignored.
+This issue is now fixed, so that builds can be canceled consistently.
diff --git a/maintainers/upload_manual.sh b/maintainers/upload_manual.sh
new file mode 100755
index 000000000..f50520490
--- /dev/null
+++ b/maintainers/upload_manual.sh
@@ -0,0 +1,40 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+cd "$(dirname -- "$0")/.."
+
+# This script uploads the Lix manual to the Lix s3 store.
+# It expects credentials to be configured like so:
+#
+# ~/.aws/credentials:
+#
+# [default]
+# aws_access_key_id = SOMEACCESSKEY
+# aws_secret_access_key = SOMESECRETKEY
+#
+# default can also be replaced by some other string if AWS_PROFILE is set in
+# environment.
+#
+# See: https://rclone.org/s3/#authentication
+#
+# To obtain such a key, log into the garage host and run:
+# (obtain GARAGE_RPC_SECRET into environment perhaps by systemctl cat garage)
+# garage key create SOME-KEY-NAME
+# garage bucket allow --read --write docs --key SOME-KEY-NAME
+
+if [[ ! -f result-doc/share/doc/nix/manual/index.html ]]; then
+ echo -e "result-doc does not appear to contain a Lix manual. You can build one with:\n nix build '.#default^*'" >&2
+ exit 1
+fi
+
+# --checksum: https://rclone.org/s3/#avoiding-head-requests-to-read-the-modification-time
+# By default rclone uses the modification time to determine if something needs
+# syncing. This is actually very bad for our use case, since we have small
+# files that have meaningless (Unix epoch) local modification time data. We can
+# make it go both 16x faster and more correct by using md5s instead.
+rclone \
+ --config doc/manual/rclone.conf \
+ -vv \
+ sync \
+ --checksum \
+ result-doc/share/doc/nix/manual/ lix-docs:docs/manual/nightly/
diff --git a/src/libcmd/repl.cc b/src/libcmd/repl.cc
index 696bb3c12..34de2160a 100644
--- a/src/libcmd/repl.cc
+++ b/src/libcmd/repl.cc
@@ -262,6 +262,8 @@ ReplExitStatus NixRepl::mainLoop()
std::string input;
while (true) {
+ _isInterrupted = false;
+
// When continuing input from previous lines, don't print a prompt, just align to the same
// number of chars as the prompt.
if (!interacter->getLine(input, input.empty() ? ReplPromptType::ReplPrompt : ReplPromptType::ContinuationPrompt)) {
@@ -424,8 +426,6 @@ ProcessLineResult NixRepl::processLine(std::string line)
if (line.empty())
return ProcessLineResult::PromptAgain;
- _isInterrupted = false;
-
std::string command, arg;
if (line[0] == ':') {
diff --git a/src/libmain/shared.cc b/src/libmain/shared.cc
index 9d4dd41ed..96ecbac8f 100644
--- a/src/libmain/shared.cc
+++ b/src/libmain/shared.cc
@@ -320,16 +320,7 @@ int handleExceptions(const std::string & programName, std::function<void()> fun)
std::string error = ANSI_RED "error:" ANSI_NORMAL " ";
try {
- try {
- fun();
- } catch (...) {
- /* Subtle: we have to make sure that any `interrupted'
- condition is discharged before we reach printMsg()
- below, since otherwise it will throw an (uncaught)
- exception. */
- setInterruptThrown();
- throw;
- }
+ fun();
} catch (Exit & e) {
return e.status;
} catch (UsageError & e) {
diff --git a/src/libstore/build/local-derivation-goal.cc b/src/libstore/build/local-derivation-goal.cc
index e7a1e0147..3429afafa 100644
--- a/src/libstore/build/local-derivation-goal.cc
+++ b/src/libstore/build/local-derivation-goal.cc
@@ -174,6 +174,10 @@ void LocalDerivationGoal::killSandbox(bool getStats)
void LocalDerivationGoal::tryLocalBuild()
{
+#if __APPLE__
+ additionalSandboxProfile = parsedDrv->getStringAttr("__sandboxProfile").value_or("");
+#endif
+
unsigned int curBuilds = worker.getNrLocalBuilds();
if (curBuilds >= settings.maxBuildJobs) {
state = &DerivationGoal::tryToBuild;
@@ -192,7 +196,6 @@ void LocalDerivationGoal::tryLocalBuild()
throw Error("derivation '%s' has '__noChroot' set, "
"but that's not allowed when 'sandbox' is 'true'", worker.store.printStorePath(drvPath));
#if __APPLE__
- additionalSandboxProfile = parsedDrv->getStringAttr("__sandboxProfile").value_or("");
if (additionalSandboxProfile != "")
throw Error("derivation '%s' specifies a sandbox profile, "
"but this is only allowed when 'sandbox' is 'relaxed'", worker.store.printStorePath(drvPath));
diff --git a/src/libstore/filetransfer.cc b/src/libstore/filetransfer.cc
index 8d508facb..492463a61 100644
--- a/src/libstore/filetransfer.cc
+++ b/src/libstore/filetransfer.cc
@@ -761,6 +761,10 @@ struct curlFileTransfer : public FileTransfer
state.wait_for(state->request, std::chrono::seconds(10));
}
+ if (state->encoding.empty()) {
+ state->encoding = transfer.encoding;
+ }
+
/* Append data to the buffer and wake up the calling
thread. */
state->data.append(data);
diff --git a/src/libutil/signals.cc b/src/libutil/signals.cc
index f5c79b325..41fdc9dc8 100644
--- a/src/libutil/signals.cc
+++ b/src/libutil/signals.cc
@@ -9,21 +9,14 @@ namespace nix {
std::atomic<bool> _isInterrupted = false;
-static thread_local bool interruptThrown = false;
thread_local std::function<bool()> interruptCheck;
-void setInterruptThrown()
-{
- interruptThrown = true;
-}
-
void _interrupted()
{
/* Block user interrupts while an exception is being handled.
Throwing an exception while another exception is being handled
kills the program! */
- if (!interruptThrown && !std::uncaught_exceptions()) {
- interruptThrown = true;
+ if (!std::uncaught_exceptions()) {
throw Interrupted("interrupted by the user");
}
}
diff --git a/src/libutil/signals.hh b/src/libutil/signals.hh
index c58dc37cf..71593df95 100644
--- a/src/libutil/signals.hh
+++ b/src/libutil/signals.hh
@@ -22,8 +22,6 @@ extern std::atomic<bool> _isInterrupted;
extern thread_local std::function<bool()> interruptCheck;
-void setInterruptThrown();
-
void _interrupted();
void inline checkInterrupt()
diff --git a/tests/functional/common/vars-and-functions.sh.in b/tests/functional/common/vars-and-functions.sh.in
index 3d2e44024..3b343b720 100644
--- a/tests/functional/common/vars-and-functions.sh.in
+++ b/tests/functional/common/vars-and-functions.sh.in
@@ -54,8 +54,6 @@ export busybox="@sandbox_shell@"
export version=@PACKAGE_VERSION@
export system=@system@
-export BUILD_SHARED_LIBS=@BUILD_SHARED_LIBS@
-
export IMPURE_VAR1=foo
export IMPURE_VAR2=bar
diff --git a/tests/functional/extra-sandbox-profile.nix b/tests/functional/extra-sandbox-profile.nix
new file mode 100644
index 000000000..aa680b918
--- /dev/null
+++ b/tests/functional/extra-sandbox-profile.nix
@@ -0,0 +1,19 @@
+{ destFile, seed }:
+
+with import ./config.nix;
+
+mkDerivation {
+ name = "simple";
+ __sandboxProfile = ''
+ # Allow writing any file in the filesystem
+ (allow file*)
+ '';
+ inherit seed;
+ buildCommand = ''
+ (
+ set -x
+ touch ${destFile}
+ touch $out
+ )
+ '';
+}
diff --git a/tests/functional/extra-sandbox-profile.sh b/tests/functional/extra-sandbox-profile.sh
new file mode 100644
index 000000000..ac3ca036f
--- /dev/null
+++ b/tests/functional/extra-sandbox-profile.sh
@@ -0,0 +1,23 @@
+source common.sh
+
+if [[ $(uname) != Darwin ]]; then skipTest "Need Darwin"; fi
+
+DEST_FILE="${TEST_ROOT}/foo"
+
+testSandboxProfile () (
+ set -e
+
+ sandboxMode="$1"
+
+ rm -f "${DEST_FILE}"
+ nix-build --no-out-link ./extra-sandbox-profile.nix \
+ --option sandbox "$sandboxMode" \
+ --argstr seed "$RANDOM" \
+ --argstr destFile "${DEST_FILE}"
+
+ ls -l "${DEST_FILE}"
+)
+
+testSandboxProfile "false"
+expectStderr 2 testSandboxProfile "true"
+testSandboxProfile "relaxed"
diff --git a/tests/functional/meson.build b/tests/functional/meson.build
index 3f4a970a7..1e68cfe8c 100644
--- a/tests/functional/meson.build
+++ b/tests/functional/meson.build
@@ -7,7 +7,6 @@ test_confdata = {
'sandbox_shell': busybox.found() ? busybox.full_path() : '',
'PACKAGE_VERSION': meson.project_version(),
'system': host_system,
- 'BUILD_SHARED_LIBS': '1', # XXX(Qyriad): detect this!
}
# Just configures `common/vars-and-functions.sh.in`.
@@ -180,10 +179,15 @@ functional_tests_scripts = [
'read-only-store.sh',
'nested-sandboxing.sh',
'debugger.sh',
- 'plugins.sh',
'test-libstoreconsumer.sh',
+ 'extra-sandbox-profile.sh',
]
+# Plugin tests require shared libraries support.
+if get_option('default_library') != 'static'
+ functional_tests_scripts += ['plugins.sh']
+endif
+
# TODO(Qyriad): this will hopefully be able to be removed when we remove the autoconf+Make
# buildsystem. See the comments at the top of setup-functional-tests.py for why this is here.
meson.add_install_script(
diff --git a/tests/functional/plugins.sh b/tests/functional/plugins.sh
index 5934b9b0c..1b6528f3b 100644
--- a/tests/functional/plugins.sh
+++ b/tests/functional/plugins.sh
@@ -1,9 +1,5 @@
source common.sh
-if [[ $BUILD_SHARED_LIBS != 1 ]]; then
- skipTest "Plugins are not supported"
-fi
-
# FIXME(Qyriad): this is working around Meson putting `libplugintest.so.p` in the same place
# as `libplugintest.so`, so `libplugintest.*` grabs both.
libext=so
diff --git a/tests/unit/libstore/filetransfer.cc b/tests/unit/libstore/filetransfer.cc
index ebd38f19d..684697c69 100644
--- a/tests/unit/libstore/filetransfer.cc
+++ b/tests/unit/libstore/filetransfer.cc
@@ -1,4 +1,5 @@
#include "filetransfer.hh"
+#include "compression.hh"
#include <cstdint>
#include <exception>
@@ -25,7 +26,7 @@ using namespace std::chrono_literals;
namespace nix {
static std::tuple<uint16_t, AutoCloseFD>
-serveHTTP(std::string_view status, std::string_view headers, std::function<std::string_view()> content)
+serveHTTP(std::string_view status, std::string_view headers, std::function<std::string()> content)
{
AutoCloseFD listener(::socket(AF_INET6, SOCK_STREAM, 0));
if (!listener) {
@@ -152,4 +153,17 @@ TEST(FileTransfer, NOT_ON_DARWIN(reportsTransferError))
req.baseRetryTimeMs = 0;
ASSERT_THROW(ft->download(req), FileTransferError);
}
+
+TEST(FileTransfer, NOT_ON_DARWIN(handlesContentEncoding))
+{
+ std::string original = "Test data string";
+ std::string compressed = compress("gzip", original);
+
+ auto [port, srv] = serveHTTP("200 ok", "content-encoding: gzip\r\n", [&] { return compressed; });
+ auto ft = makeFileTransfer();
+
+ StringSink sink;
+ ft->download(FileTransferRequest(fmt("http://[::1]:%d/index", port)), sink);
+ EXPECT_EQ(sink.s, original);
+}
}