diff options
-rw-r--r-- | doc/manual/rclone.conf | 8 | ||||
-rw-r--r-- | doc/manual/rl-next/repl-interrupt.md | 8 | ||||
-rwxr-xr-x | maintainers/upload_manual.sh | 40 | ||||
-rw-r--r-- | src/libcmd/repl.cc | 4 | ||||
-rw-r--r-- | src/libmain/shared.cc | 11 | ||||
-rw-r--r-- | src/libstore/build/local-derivation-goal.cc | 5 | ||||
-rw-r--r-- | src/libstore/filetransfer.cc | 4 | ||||
-rw-r--r-- | src/libutil/signals.cc | 9 | ||||
-rw-r--r-- | src/libutil/signals.hh | 2 | ||||
-rw-r--r-- | tests/functional/common/vars-and-functions.sh.in | 2 | ||||
-rw-r--r-- | tests/functional/extra-sandbox-profile.nix | 19 | ||||
-rw-r--r-- | tests/functional/extra-sandbox-profile.sh | 23 | ||||
-rw-r--r-- | tests/functional/meson.build | 8 | ||||
-rw-r--r-- | tests/functional/plugins.sh | 4 | ||||
-rw-r--r-- | tests/unit/libstore/filetransfer.cc | 16 |
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); +} } |